| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * SSL v2 handshake functions, and functions common to SSL2 and SSL3. | |
| 3 * | |
| 4 * This Source Code Form is subject to the terms of the Mozilla Public | |
| 5 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 7 | |
| 8 #include "nssrenam.h" | |
| 9 #include "cert.h" | |
| 10 #include "secitem.h" | |
| 11 #include "sechash.h" | |
| 12 #include "cryptohi.h" /* for SGN_ funcs */ | |
| 13 #include "keyhi.h" /* for SECKEY_ high level functions. */ | |
| 14 #include "ssl.h" | |
| 15 #include "sslimpl.h" | |
| 16 #include "sslproto.h" | |
| 17 #include "ssl3prot.h" | |
| 18 #include "sslerr.h" | |
| 19 #include "pk11func.h" | |
| 20 #include "prinit.h" | |
| 21 #include "prtime.h" /* for PR_Now() */ | |
| 22 | |
| 23 static PRBool policyWasSet; | |
| 24 | |
| 25 /* This ordered list is indexed by (SSL_CK_xx * 3) */ | |
| 26 /* Second and third bytes are MSB and LSB of master key length. */ | |
| 27 static const PRUint8 allCipherSuites[] = { | |
| 28 0, 0, 0, | |
| 29 SSL_CK_RC4_128_WITH_MD5, 0x00, 0x80, | |
| 30 SSL_CK_RC4_128_EXPORT40_WITH_MD5, 0x00, 0x80, | |
| 31 SSL_CK_RC2_128_CBC_WITH_MD5, 0x00, 0x80, | |
| 32 SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, 0x00, 0x80, | |
| 33 SSL_CK_IDEA_128_CBC_WITH_MD5, 0x00, 0x80, | |
| 34 SSL_CK_DES_64_CBC_WITH_MD5, 0x00, 0x40, | |
| 35 SSL_CK_DES_192_EDE3_CBC_WITH_MD5, 0x00, 0xC0, | |
| 36 0, 0, 0 | |
| 37 }; | |
| 38 | |
| 39 #define ssl2_NUM_SUITES_IMPLEMENTED 6 | |
| 40 | |
| 41 /* This list is sent back to the client when the client-hello message | |
| 42 * contains no overlapping ciphers, so the client can report what ciphers | |
| 43 * are supported by the server. Unlike allCipherSuites (above), this list | |
| 44 * is sorted by descending preference, not by cipherSuite number. | |
| 45 */ | |
| 46 static const PRUint8 implementedCipherSuites[ssl2_NUM_SUITES_IMPLEMENTED * 3] =
{ | |
| 47 SSL_CK_RC4_128_WITH_MD5, 0x00, 0x80, | |
| 48 SSL_CK_RC2_128_CBC_WITH_MD5, 0x00, 0x80, | |
| 49 SSL_CK_DES_192_EDE3_CBC_WITH_MD5, 0x00, 0xC0, | |
| 50 SSL_CK_DES_64_CBC_WITH_MD5, 0x00, 0x40, | |
| 51 SSL_CK_RC4_128_EXPORT40_WITH_MD5, 0x00, 0x80, | |
| 52 SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, 0x00, 0x80 | |
| 53 }; | |
| 54 | |
| 55 typedef struct ssl2SpecsStr { | |
| 56 PRUint8 nkm; /* do this many hashes to generate key material. */ | |
| 57 PRUint8 nkd; /* size of readKey and writeKey in bytes. */ | |
| 58 PRUint8 blockSize; | |
| 59 PRUint8 blockShift; | |
| 60 CK_MECHANISM_TYPE mechanism; | |
| 61 PRUint8 keyLen; /* cipher symkey size in bytes. */ | |
| 62 PRUint8 pubLen; /* publicly reveal this many bytes of key. */ | |
| 63 PRUint8 ivLen; /* length of IV data at *ca. */ | |
| 64 } ssl2Specs; | |
| 65 | |
| 66 static const ssl2Specs ssl_Specs[] = { | |
| 67 /* NONE */ | |
| 68 { 0, 0, 0, 0, }, | |
| 69 /* SSL_CK_RC4_128_WITH_MD5 */ | |
| 70 { 2, 16, 1, 0, CKM_RC4, 16, 0, 0, }, | |
| 71 /* SSL_CK_RC4_128_EXPORT40_WITH_MD5 */ | |
| 72 { 2, 16, 1, 0, CKM_RC4, 16, 11, 0, }, | |
| 73 /* SSL_CK_RC2_128_CBC_WITH_MD5 */ | |
| 74 { 2, 16, 8, 3, CKM_RC2_CBC, 16, 0, 8, }, | |
| 75 /* SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 */ | |
| 76 { 2, 16, 8, 3, CKM_RC2_CBC, 16, 11, 8, }, | |
| 77 /* SSL_CK_IDEA_128_CBC_WITH_MD5 */ | |
| 78 { 0, 0, 0, 0, }, | |
| 79 /* SSL_CK_DES_64_CBC_WITH_MD5 */ | |
| 80 { 1, 8, 8, 3, CKM_DES_CBC, 8, 0, 8, }, | |
| 81 /* SSL_CK_DES_192_EDE3_CBC_WITH_MD5 */ | |
| 82 { 3, 24, 8, 3, CKM_DES3_CBC, 24, 0, 8, }, | |
| 83 }; | |
| 84 | |
| 85 #define SET_ERROR_CODE /* reminder */ | |
| 86 #define TEST_FOR_FAILURE /* reminder */ | |
| 87 | |
| 88 /* | |
| 89 ** Put a string tag in the library so that we can examine an executable | |
| 90 ** and see what kind of security it supports. | |
| 91 */ | |
| 92 const char *ssl_version = "SECURITY_VERSION:" | |
| 93 " +us" | |
| 94 " +export" | |
| 95 #ifdef TRACE | |
| 96 " +trace" | |
| 97 #endif | |
| 98 #ifdef DEBUG | |
| 99 " +debug" | |
| 100 #endif | |
| 101 ; | |
| 102 | |
| 103 const char * const ssl_cipherName[] = { | |
| 104 "unknown", | |
| 105 "RC4", | |
| 106 "RC4-Export", | |
| 107 "RC2-CBC", | |
| 108 "RC2-CBC-Export", | |
| 109 "IDEA-CBC", | |
| 110 "DES-CBC", | |
| 111 "DES-EDE3-CBC", | |
| 112 "unknown", | |
| 113 "unknown", /* was fortezza, NO LONGER USED */ | |
| 114 }; | |
| 115 | |
| 116 | |
| 117 /* bit-masks, showing which SSLv2 suites are allowed. | |
| 118 * lsb corresponds to first cipher suite in allCipherSuites[]. | |
| 119 */ | |
| 120 static PRUint16 allowedByPolicy; /* all off by default */ | |
| 121 static PRUint16 maybeAllowedByPolicy; /* all off by default */ | |
| 122 static PRUint16 chosenPreference = 0xff; /* all on by default */ | |
| 123 | |
| 124 /* bit values for the above two bit masks */ | |
| 125 #define SSL_CB_RC4_128_WITH_MD5 (1 << SSL_CK_RC4_128_WITH_MD5) | |
| 126 #define SSL_CB_RC4_128_EXPORT40_WITH_MD5 (1 << SSL_CK_RC4_128_EXPORT40_WITH_
MD5) | |
| 127 #define SSL_CB_RC2_128_CBC_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_WITH_MD5) | |
| 128 #define SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 (1 << SSL_CK_RC2_128_CBC_EXPORT40_W
ITH_MD5) | |
| 129 #define SSL_CB_IDEA_128_CBC_WITH_MD5 (1 << SSL_CK_IDEA_128_CBC_WITH_MD5) | |
| 130 #define SSL_CB_DES_64_CBC_WITH_MD5 (1 << SSL_CK_DES_64_CBC_WITH_MD5) | |
| 131 #define SSL_CB_DES_192_EDE3_CBC_WITH_MD5 (1 << SSL_CK_DES_192_EDE3_CBC_WITH_
MD5) | |
| 132 #define SSL_CB_IMPLEMENTED \ | |
| 133 (SSL_CB_RC4_128_WITH_MD5 | \ | |
| 134 SSL_CB_RC4_128_EXPORT40_WITH_MD5 | \ | |
| 135 SSL_CB_RC2_128_CBC_WITH_MD5 | \ | |
| 136 SSL_CB_RC2_128_CBC_EXPORT40_WITH_MD5 | \ | |
| 137 SSL_CB_DES_64_CBC_WITH_MD5 | \ | |
| 138 SSL_CB_DES_192_EDE3_CBC_WITH_MD5) | |
| 139 | |
| 140 | |
| 141 /* Construct a socket's list of cipher specs from the global default values. | |
| 142 */ | |
| 143 static SECStatus | |
| 144 ssl2_ConstructCipherSpecs(sslSocket *ss) | |
| 145 { | |
| 146 PRUint8 * cs = NULL; | |
| 147 unsigned int allowed; | |
| 148 unsigned int count; | |
| 149 int ssl3_count = 0; | |
| 150 int final_count; | |
| 151 int i; | |
| 152 SECStatus rv; | |
| 153 | |
| 154 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 155 | |
| 156 count = 0; | |
| 157 PORT_Assert(ss != 0); | |
| 158 allowed = !ss->opt.enableSSL2 ? 0 : | |
| 159 (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED); | |
| 160 while (allowed) { | |
| 161 if (allowed & 1) | |
| 162 ++count; | |
| 163 allowed >>= 1; | |
| 164 } | |
| 165 | |
| 166 /* Call ssl3_config_match_init() once here, | |
| 167 * instead of inside ssl3_ConstructV2CipherSpecsHack(), | |
| 168 * because the latter gets called twice below, | |
| 169 * and then again in ssl2_BeginClientHandshake(). | |
| 170 */ | |
| 171 ssl3_config_match_init(ss); | |
| 172 | |
| 173 /* ask SSL3 how many cipher suites it has. */ | |
| 174 rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3_count); | |
| 175 if (rv < 0) | |
| 176 return rv; | |
| 177 count += ssl3_count; | |
| 178 | |
| 179 /* Allocate memory to hold cipher specs */ | |
| 180 if (count > 0) | |
| 181 cs = (PRUint8*) PORT_Alloc(count * 3); | |
| 182 else | |
| 183 PORT_SetError(SSL_ERROR_SSL_DISABLED); | |
| 184 if (cs == NULL) | |
| 185 return SECFailure; | |
| 186 | |
| 187 if (ss->cipherSpecs != NULL) { | |
| 188 PORT_Free(ss->cipherSpecs); | |
| 189 } | |
| 190 ss->cipherSpecs = cs; | |
| 191 ss->sizeCipherSpecs = count * 3; | |
| 192 | |
| 193 /* fill in cipher specs for SSL2 cipher suites */ | |
| 194 allowed = !ss->opt.enableSSL2 ? 0 : | |
| 195 (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED); | |
| 196 for (i = 0; i < ssl2_NUM_SUITES_IMPLEMENTED * 3; i += 3) { | |
| 197 const PRUint8 * hs = implementedCipherSuites + i; | |
| 198 int ok = allowed & (1U << hs[0]); | |
| 199 if (ok) { | |
| 200 cs[0] = hs[0]; | |
| 201 cs[1] = hs[1]; | |
| 202 cs[2] = hs[2]; | |
| 203 cs += 3; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 /* now have SSL3 add its suites onto the end */ | |
| 208 rv = ssl3_ConstructV2CipherSpecsHack(ss, cs, &final_count); | |
| 209 | |
| 210 /* adjust for any difference between first pass and second pass */ | |
| 211 ss->sizeCipherSpecs -= (ssl3_count - final_count) * 3; | |
| 212 | |
| 213 return rv; | |
| 214 } | |
| 215 | |
| 216 /* This function is called immediately after ssl2_ConstructCipherSpecs() | |
| 217 ** at the beginning of a handshake. It detects cases where a protocol | |
| 218 ** (e.g. SSL2 or SSL3) is logically enabled, but all its cipher suites | |
| 219 ** for that protocol have been disabled. If such cases, it clears the | |
| 220 ** enable bit for the protocol. If no protocols remain enabled, or | |
| 221 ** if no cipher suites are found, it sets the error code and returns | |
| 222 ** SECFailure, otherwise it returns SECSuccess. | |
| 223 */ | |
| 224 static SECStatus | |
| 225 ssl2_CheckConfigSanity(sslSocket *ss) | |
| 226 { | |
| 227 unsigned int allowed; | |
| 228 int ssl3CipherCount = 0; | |
| 229 SECStatus rv; | |
| 230 | |
| 231 /* count the SSL2 and SSL3 enabled ciphers. | |
| 232 * if either is zero, clear the socket's enable for that protocol. | |
| 233 */ | |
| 234 if (!ss->cipherSpecs) | |
| 235 goto disabled; | |
| 236 | |
| 237 allowed = ss->allowedByPolicy & ss->chosenPreference; | |
| 238 if (! allowed) | |
| 239 ss->opt.enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */ | |
| 240 | |
| 241 /* ssl3_config_match_init was called in ssl2_ConstructCipherSpecs(). */ | |
| 242 /* Ask how many ssl3 CipherSuites were enabled. */ | |
| 243 rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3CipherCount); | |
| 244 if (rv != SECSuccess || ssl3CipherCount <= 0) { | |
| 245 /* SSL3/TLS not really enabled if no ciphers */ | |
| 246 ss->vrange.min = SSL_LIBRARY_VERSION_NONE; | |
| 247 ss->vrange.max = SSL_LIBRARY_VERSION_NONE; | |
| 248 } | |
| 249 | |
| 250 if (!ss->opt.enableSSL2 && SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { | |
| 251 SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.", | |
| 252 SSL_GETPID(), ss->fd)); | |
| 253 disabled: | |
| 254 PORT_SetError(SSL_ERROR_SSL_DISABLED); | |
| 255 return SECFailure; | |
| 256 } | |
| 257 return SECSuccess; | |
| 258 } | |
| 259 | |
| 260 /* | |
| 261 * Since this is a global (not per-socket) setting, we cannot use the | |
| 262 * HandshakeLock to protect this. Probably want a global lock. | |
| 263 */ | |
| 264 SECStatus | |
| 265 ssl2_SetPolicy(PRInt32 which, PRInt32 policy) | |
| 266 { | |
| 267 PRUint32 bitMask; | |
| 268 SECStatus rv = SECSuccess; | |
| 269 | |
| 270 which &= 0x000f; | |
| 271 bitMask = 1 << which; | |
| 272 | |
| 273 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 274 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 275 return SECFailure; | |
| 276 } | |
| 277 | |
| 278 if (policy == SSL_ALLOWED) { | |
| 279 allowedByPolicy |= bitMask; | |
| 280 maybeAllowedByPolicy |= bitMask; | |
| 281 } else if (policy == SSL_RESTRICTED) { | |
| 282 allowedByPolicy &= ~bitMask; | |
| 283 maybeAllowedByPolicy |= bitMask; | |
| 284 } else { | |
| 285 allowedByPolicy &= ~bitMask; | |
| 286 maybeAllowedByPolicy &= ~bitMask; | |
| 287 } | |
| 288 allowedByPolicy &= SSL_CB_IMPLEMENTED; | |
| 289 maybeAllowedByPolicy &= SSL_CB_IMPLEMENTED; | |
| 290 | |
| 291 policyWasSet = PR_TRUE; | |
| 292 return rv; | |
| 293 } | |
| 294 | |
| 295 SECStatus | |
| 296 ssl2_GetPolicy(PRInt32 which, PRInt32 *oPolicy) | |
| 297 { | |
| 298 PRUint32 bitMask; | |
| 299 PRInt32 policy; | |
| 300 | |
| 301 which &= 0x000f; | |
| 302 bitMask = 1 << which; | |
| 303 | |
| 304 /* Caller assures oPolicy is not null. */ | |
| 305 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 306 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 307 *oPolicy = SSL_NOT_ALLOWED; | |
| 308 return SECFailure; | |
| 309 } | |
| 310 | |
| 311 if (maybeAllowedByPolicy & bitMask) { | |
| 312 policy = (allowedByPolicy & bitMask) ? SSL_ALLOWED : SSL_RESTRICTED; | |
| 313 } else { | |
| 314 policy = SSL_NOT_ALLOWED; | |
| 315 } | |
| 316 | |
| 317 *oPolicy = policy; | |
| 318 return SECSuccess; | |
| 319 } | |
| 320 | |
| 321 /* | |
| 322 * Since this is a global (not per-socket) setting, we cannot use the | |
| 323 * HandshakeLock to protect this. Probably want a global lock. | |
| 324 * Called from SSL_CipherPrefSetDefault in sslsock.c | |
| 325 * These changes have no effect on any sslSockets already created. | |
| 326 */ | |
| 327 SECStatus | |
| 328 ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled) | |
| 329 { | |
| 330 PRUint32 bitMask; | |
| 331 | |
| 332 which &= 0x000f; | |
| 333 bitMask = 1 << which; | |
| 334 | |
| 335 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 336 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 337 return SECFailure; | |
| 338 } | |
| 339 | |
| 340 if (enabled) | |
| 341 chosenPreference |= bitMask; | |
| 342 else | |
| 343 chosenPreference &= ~bitMask; | |
| 344 chosenPreference &= SSL_CB_IMPLEMENTED; | |
| 345 | |
| 346 return SECSuccess; | |
| 347 } | |
| 348 | |
| 349 SECStatus | |
| 350 ssl2_CipherPrefGetDefault(PRInt32 which, PRBool *enabled) | |
| 351 { | |
| 352 PRBool rv = PR_FALSE; | |
| 353 PRUint32 bitMask; | |
| 354 | |
| 355 which &= 0x000f; | |
| 356 bitMask = 1 << which; | |
| 357 | |
| 358 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 359 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 360 *enabled = PR_FALSE; | |
| 361 return SECFailure; | |
| 362 } | |
| 363 | |
| 364 rv = (PRBool)((chosenPreference & bitMask) != 0); | |
| 365 *enabled = rv; | |
| 366 return SECSuccess; | |
| 367 } | |
| 368 | |
| 369 SECStatus | |
| 370 ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled) | |
| 371 { | |
| 372 PRUint32 bitMask; | |
| 373 | |
| 374 which &= 0x000f; | |
| 375 bitMask = 1 << which; | |
| 376 | |
| 377 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 378 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 379 return SECFailure; | |
| 380 } | |
| 381 | |
| 382 if (enabled) | |
| 383 ss->chosenPreference |= bitMask; | |
| 384 else | |
| 385 ss->chosenPreference &= ~bitMask; | |
| 386 ss->chosenPreference &= SSL_CB_IMPLEMENTED; | |
| 387 | |
| 388 return SECSuccess; | |
| 389 } | |
| 390 | |
| 391 SECStatus | |
| 392 ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled) | |
| 393 { | |
| 394 PRBool rv = PR_FALSE; | |
| 395 PRUint32 bitMask; | |
| 396 | |
| 397 which &= 0x000f; | |
| 398 bitMask = 1 << which; | |
| 399 | |
| 400 if (!(bitMask & SSL_CB_IMPLEMENTED)) { | |
| 401 PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); | |
| 402 *enabled = PR_FALSE; | |
| 403 return SECFailure; | |
| 404 } | |
| 405 | |
| 406 rv = (PRBool)((ss->chosenPreference & bitMask) != 0); | |
| 407 *enabled = rv; | |
| 408 return SECSuccess; | |
| 409 } | |
| 410 | |
| 411 | |
| 412 /* copy global default policy into socket. */ | |
| 413 void | |
| 414 ssl2_InitSocketPolicy(sslSocket *ss) | |
| 415 { | |
| 416 ss->allowedByPolicy = allowedByPolicy; | |
| 417 ss->maybeAllowedByPolicy = maybeAllowedByPolicy; | |
| 418 ss->chosenPreference = chosenPreference; | |
| 419 } | |
| 420 | |
| 421 | |
| 422 /************************************************************************/ | |
| 423 | |
| 424 /* Called from ssl2_CreateSessionCypher(), which already holds handshake lock. | |
| 425 */ | |
| 426 static SECStatus | |
| 427 ssl2_CreateMAC(sslSecurityInfo *sec, SECItem *readKey, SECItem *writeKey, | |
| 428 int cipherChoice) | |
| 429 { | |
| 430 switch (cipherChoice) { | |
| 431 | |
| 432 case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: | |
| 433 case SSL_CK_RC2_128_CBC_WITH_MD5: | |
| 434 case SSL_CK_RC4_128_EXPORT40_WITH_MD5: | |
| 435 case SSL_CK_RC4_128_WITH_MD5: | |
| 436 case SSL_CK_DES_64_CBC_WITH_MD5: | |
| 437 case SSL_CK_DES_192_EDE3_CBC_WITH_MD5: | |
| 438 sec->hash = HASH_GetHashObject(HASH_AlgMD5); | |
| 439 SECITEM_CopyItem(0, &sec->sendSecret, writeKey); | |
| 440 SECITEM_CopyItem(0, &sec->rcvSecret, readKey); | |
| 441 break; | |
| 442 | |
| 443 default: | |
| 444 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 445 return SECFailure; | |
| 446 } | |
| 447 sec->hashcx = (*sec->hash->create)(); | |
| 448 if (sec->hashcx == NULL) | |
| 449 return SECFailure; | |
| 450 return SECSuccess; | |
| 451 } | |
| 452 | |
| 453 /************************************************************************ | |
| 454 * All the Send functions below must acquire and release the socket's | |
| 455 * xmitBufLock. | |
| 456 */ | |
| 457 | |
| 458 /* Called from all the Send* functions below. */ | |
| 459 static SECStatus | |
| 460 ssl2_GetSendBuffer(sslSocket *ss, unsigned int len) | |
| 461 { | |
| 462 SECStatus rv = SECSuccess; | |
| 463 | |
| 464 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 465 | |
| 466 if (len < 128) { | |
| 467 len = 128; | |
| 468 } | |
| 469 if (len > ss->sec.ci.sendBuf.space) { | |
| 470 rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, len); | |
| 471 if (rv != SECSuccess) { | |
| 472 SSL_DBG(("%d: SSL[%d]: ssl2_GetSendBuffer failed, tried to get %d by
tes", | |
| 473 SSL_GETPID(), ss->fd, len)); | |
| 474 rv = SECFailure; | |
| 475 } | |
| 476 } | |
| 477 return rv; | |
| 478 } | |
| 479 | |
| 480 /* Called from: | |
| 481 * ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage() | |
| 482 * ssl2_HandleRequestCertificate() <- ssl2_HandleMessage() <- | |
| 483 ssl_Do1stHandshake() | |
| 484 * ssl2_HandleMessage() <- ssl_Do1stHandshake() | |
| 485 * ssl2_HandleServerHelloMessage() <- ssl_Do1stHandshake() | |
| 486 after ssl2_BeginClientHandshake() | |
| 487 * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake() | |
| 488 after ssl2_BeginServerHandshake() | |
| 489 * | |
| 490 * Acquires and releases the socket's xmitBufLock. | |
| 491 */ | |
| 492 int | |
| 493 ssl2_SendErrorMessage(sslSocket *ss, int error) | |
| 494 { | |
| 495 int rv; | |
| 496 PRUint8 msg[SSL_HL_ERROR_HBYTES]; | |
| 497 | |
| 498 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 499 | |
| 500 msg[0] = SSL_MT_ERROR; | |
| 501 msg[1] = MSB(error); | |
| 502 msg[2] = LSB(error); | |
| 503 | |
| 504 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 505 | |
| 506 SSL_TRC(3, ("%d: SSL[%d]: sending error %d", SSL_GETPID(), ss->fd, error)); | |
| 507 | |
| 508 ss->handshakeBegun = 1; | |
| 509 rv = (*ss->sec.send)(ss, msg, sizeof(msg), 0); | |
| 510 if (rv >= 0) { | |
| 511 rv = SECSuccess; | |
| 512 } | |
| 513 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 514 return rv; | |
| 515 } | |
| 516 | |
| 517 /* Called from ssl2_TryToFinish(). | |
| 518 * Acquires and releases the socket's xmitBufLock. | |
| 519 */ | |
| 520 static SECStatus | |
| 521 ssl2_SendClientFinishedMessage(sslSocket *ss) | |
| 522 { | |
| 523 SECStatus rv = SECSuccess; | |
| 524 int sent; | |
| 525 PRUint8 msg[1 + SSL_CONNECTIONID_BYTES]; | |
| 526 | |
| 527 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 528 | |
| 529 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 530 | |
| 531 if (ss->sec.ci.sentFinished == 0) { | |
| 532 ss->sec.ci.sentFinished = 1; | |
| 533 | |
| 534 SSL_TRC(3, ("%d: SSL[%d]: sending client-finished", | |
| 535 SSL_GETPID(), ss->fd)); | |
| 536 | |
| 537 msg[0] = SSL_MT_CLIENT_FINISHED; | |
| 538 PORT_Memcpy(msg+1, ss->sec.ci.connectionID, | |
| 539 sizeof(ss->sec.ci.connectionID)); | |
| 540 | |
| 541 DUMP_MSG(29, (ss, msg, 1 + sizeof(ss->sec.ci.connectionID))); | |
| 542 sent = (*ss->sec.send)(ss, msg, 1 + sizeof(ss->sec.ci.connectionID), 0); | |
| 543 rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; | |
| 544 } | |
| 545 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 546 return rv; | |
| 547 } | |
| 548 | |
| 549 /* Called from | |
| 550 * ssl2_HandleClientSessionKeyMessage() <- ssl2_HandleClientHelloMessage() | |
| 551 * ssl2_HandleClientHelloMessage() <- ssl_Do1stHandshake() | |
| 552 after ssl2_BeginServerHandshake() | |
| 553 * Acquires and releases the socket's xmitBufLock. | |
| 554 */ | |
| 555 static SECStatus | |
| 556 ssl2_SendServerVerifyMessage(sslSocket *ss) | |
| 557 { | |
| 558 PRUint8 * msg; | |
| 559 int sendLen; | |
| 560 int sent; | |
| 561 SECStatus rv; | |
| 562 | |
| 563 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 564 | |
| 565 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 566 | |
| 567 sendLen = 1 + SSL_CHALLENGE_BYTES; | |
| 568 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 569 if (rv != SECSuccess) { | |
| 570 goto done; | |
| 571 } | |
| 572 | |
| 573 msg = ss->sec.ci.sendBuf.buf; | |
| 574 msg[0] = SSL_MT_SERVER_VERIFY; | |
| 575 PORT_Memcpy(msg+1, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES); | |
| 576 | |
| 577 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 578 sent = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 579 | |
| 580 rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; | |
| 581 | |
| 582 done: | |
| 583 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 584 return rv; | |
| 585 } | |
| 586 | |
| 587 /* Called from ssl2_TryToFinish(). | |
| 588 * Acquires and releases the socket's xmitBufLock. | |
| 589 */ | |
| 590 static SECStatus | |
| 591 ssl2_SendServerFinishedMessage(sslSocket *ss) | |
| 592 { | |
| 593 sslSessionID * sid; | |
| 594 PRUint8 * msg; | |
| 595 int sendLen, sent; | |
| 596 SECStatus rv = SECSuccess; | |
| 597 | |
| 598 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 599 | |
| 600 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 601 | |
| 602 if (ss->sec.ci.sentFinished == 0) { | |
| 603 ss->sec.ci.sentFinished = 1; | |
| 604 PORT_Assert(ss->sec.ci.sid != 0); | |
| 605 sid = ss->sec.ci.sid; | |
| 606 | |
| 607 SSL_TRC(3, ("%d: SSL[%d]: sending server-finished", | |
| 608 SSL_GETPID(), ss->fd)); | |
| 609 | |
| 610 sendLen = 1 + sizeof(sid->u.ssl2.sessionID); | |
| 611 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 612 if (rv != SECSuccess) { | |
| 613 goto done; | |
| 614 } | |
| 615 | |
| 616 msg = ss->sec.ci.sendBuf.buf; | |
| 617 msg[0] = SSL_MT_SERVER_FINISHED; | |
| 618 PORT_Memcpy(msg+1, sid->u.ssl2.sessionID, | |
| 619 sizeof(sid->u.ssl2.sessionID)); | |
| 620 | |
| 621 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 622 sent = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 623 | |
| 624 if (sent < 0) { | |
| 625 /* If send failed, it is now a bogus session-id */ | |
| 626 if (ss->sec.uncache) | |
| 627 (*ss->sec.uncache)(sid); | |
| 628 rv = (SECStatus)sent; | |
| 629 } else if (!ss->opt.noCache) { | |
| 630 if (sid->cached == never_cached) { | |
| 631 (*ss->sec.cache)(sid); | |
| 632 } | |
| 633 rv = SECSuccess; | |
| 634 } | |
| 635 ssl_FreeSID(sid); | |
| 636 ss->sec.ci.sid = 0; | |
| 637 } | |
| 638 done: | |
| 639 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 640 return rv; | |
| 641 } | |
| 642 | |
| 643 /* Called from ssl2_ClientSetupSessionCypher() <- | |
| 644 * ssl2_HandleServerHelloMessage() | |
| 645 * after ssl2_BeginClientHandshake() | |
| 646 * Acquires and releases the socket's xmitBufLock. | |
| 647 */ | |
| 648 static SECStatus | |
| 649 ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize, | |
| 650 PRUint8 *ca, int caLen, | |
| 651 PRUint8 *ck, int ckLen, | |
| 652 PRUint8 *ek, int ekLen) | |
| 653 { | |
| 654 PRUint8 * msg; | |
| 655 int sendLen; | |
| 656 int sent; | |
| 657 SECStatus rv; | |
| 658 | |
| 659 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 660 | |
| 661 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 662 | |
| 663 sendLen = SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen; | |
| 664 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 665 if (rv != SECSuccess) | |
| 666 goto done; | |
| 667 | |
| 668 SSL_TRC(3, ("%d: SSL[%d]: sending client-session-key", | |
| 669 SSL_GETPID(), ss->fd)); | |
| 670 | |
| 671 msg = ss->sec.ci.sendBuf.buf; | |
| 672 msg[0] = SSL_MT_CLIENT_MASTER_KEY; | |
| 673 msg[1] = cipher; | |
| 674 msg[2] = MSB(keySize); | |
| 675 msg[3] = LSB(keySize); | |
| 676 msg[4] = MSB(ckLen); | |
| 677 msg[5] = LSB(ckLen); | |
| 678 msg[6] = MSB(ekLen); | |
| 679 msg[7] = LSB(ekLen); | |
| 680 msg[8] = MSB(caLen); | |
| 681 msg[9] = LSB(caLen); | |
| 682 PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES, ck, ckLen); | |
| 683 PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES+ckLen, ek, ekLen); | |
| 684 PORT_Memcpy(msg+SSL_HL_CLIENT_MASTER_KEY_HBYTES+ckLen+ekLen, ca, caLen); | |
| 685 | |
| 686 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 687 sent = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 688 rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; | |
| 689 done: | |
| 690 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 691 return rv; | |
| 692 } | |
| 693 | |
| 694 /* Called from ssl2_TriggerNextMessage() <- ssl2_HandleMessage() | |
| 695 * Acquires and releases the socket's xmitBufLock. | |
| 696 */ | |
| 697 static SECStatus | |
| 698 ssl2_SendCertificateRequestMessage(sslSocket *ss) | |
| 699 { | |
| 700 PRUint8 * msg; | |
| 701 int sent; | |
| 702 int sendLen; | |
| 703 SECStatus rv; | |
| 704 | |
| 705 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 706 | |
| 707 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 708 | |
| 709 sendLen = SSL_HL_REQUEST_CERTIFICATE_HBYTES + SSL_CHALLENGE_BYTES; | |
| 710 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 711 if (rv != SECSuccess) | |
| 712 goto done; | |
| 713 | |
| 714 SSL_TRC(3, ("%d: SSL[%d]: sending certificate request", | |
| 715 SSL_GETPID(), ss->fd)); | |
| 716 | |
| 717 /* Generate random challenge for client to encrypt */ | |
| 718 PK11_GenerateRandom(ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES); | |
| 719 | |
| 720 msg = ss->sec.ci.sendBuf.buf; | |
| 721 msg[0] = SSL_MT_REQUEST_CERTIFICATE; | |
| 722 msg[1] = SSL_AT_MD5_WITH_RSA_ENCRYPTION; | |
| 723 PORT_Memcpy(msg + SSL_HL_REQUEST_CERTIFICATE_HBYTES, | |
| 724 ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES); | |
| 725 | |
| 726 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 727 sent = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 728 rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; | |
| 729 done: | |
| 730 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 731 return rv; | |
| 732 } | |
| 733 | |
| 734 /* Called from ssl2_HandleRequestCertificate() <- ssl2_HandleMessage() | |
| 735 * Acquires and releases the socket's xmitBufLock. | |
| 736 */ | |
| 737 static int | |
| 738 ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert, | |
| 739 SECItem *encCode) | |
| 740 { | |
| 741 PRUint8 *msg; | |
| 742 int rv, sendLen; | |
| 743 | |
| 744 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 745 | |
| 746 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 747 | |
| 748 sendLen = SSL_HL_CLIENT_CERTIFICATE_HBYTES + encCode->len + cert->len; | |
| 749 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 750 if (rv) | |
| 751 goto done; | |
| 752 | |
| 753 SSL_TRC(3, ("%d: SSL[%d]: sending certificate response", | |
| 754 SSL_GETPID(), ss->fd)); | |
| 755 | |
| 756 msg = ss->sec.ci.sendBuf.buf; | |
| 757 msg[0] = SSL_MT_CLIENT_CERTIFICATE; | |
| 758 msg[1] = SSL_CT_X509_CERTIFICATE; | |
| 759 msg[2] = MSB(cert->len); | |
| 760 msg[3] = LSB(cert->len); | |
| 761 msg[4] = MSB(encCode->len); | |
| 762 msg[5] = LSB(encCode->len); | |
| 763 PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES, cert->data, cert->len); | |
| 764 PORT_Memcpy(msg + SSL_HL_CLIENT_CERTIFICATE_HBYTES + cert->len, | |
| 765 encCode->data, encCode->len); | |
| 766 | |
| 767 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 768 rv = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 769 if (rv >= 0) { | |
| 770 rv = SECSuccess; | |
| 771 } | |
| 772 done: | |
| 773 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 774 return rv; | |
| 775 } | |
| 776 | |
| 777 /******************************************************************** | |
| 778 ** Send functions above this line must aquire & release the socket's | |
| 779 ** xmitBufLock. | |
| 780 ** All the ssl2_Send functions below this line are called vis ss->sec.send | |
| 781 ** and require that the caller hold the xmitBufLock. | |
| 782 */ | |
| 783 | |
| 784 /* | |
| 785 ** Called from ssl2_SendStream, ssl2_SendBlock, but not from ssl2_SendClear. | |
| 786 */ | |
| 787 static SECStatus | |
| 788 ssl2_CalcMAC(PRUint8 * result, | |
| 789 sslSecurityInfo * sec, | |
| 790 const PRUint8 * data, | |
| 791 unsigned int dataLen, | |
| 792 unsigned int paddingLen) | |
| 793 { | |
| 794 const PRUint8 * secret = sec->sendSecret.data; | |
| 795 unsigned int secretLen = sec->sendSecret.len; | |
| 796 unsigned long sequenceNumber = sec->sendSequence; | |
| 797 unsigned int nout; | |
| 798 PRUint8 seq[4]; | |
| 799 PRUint8 padding[32];/* XXX max blocksize? */ | |
| 800 | |
| 801 if (!sec->hash || !sec->hash->length) | |
| 802 return SECSuccess; | |
| 803 if (!sec->hashcx) | |
| 804 return SECFailure; | |
| 805 | |
| 806 /* Reset hash function */ | |
| 807 (*sec->hash->begin)(sec->hashcx); | |
| 808 | |
| 809 /* Feed hash the data */ | |
| 810 (*sec->hash->update)(sec->hashcx, secret, secretLen); | |
| 811 (*sec->hash->update)(sec->hashcx, data, dataLen); | |
| 812 PORT_Memset(padding, paddingLen, paddingLen); | |
| 813 (*sec->hash->update)(sec->hashcx, padding, paddingLen); | |
| 814 | |
| 815 seq[0] = (PRUint8) (sequenceNumber >> 24); | |
| 816 seq[1] = (PRUint8) (sequenceNumber >> 16); | |
| 817 seq[2] = (PRUint8) (sequenceNumber >> 8); | |
| 818 seq[3] = (PRUint8) (sequenceNumber); | |
| 819 | |
| 820 PRINT_BUF(60, (0, "calc-mac secret:", secret, secretLen)); | |
| 821 PRINT_BUF(60, (0, "calc-mac data:", data, dataLen)); | |
| 822 PRINT_BUF(60, (0, "calc-mac padding:", padding, paddingLen)); | |
| 823 PRINT_BUF(60, (0, "calc-mac seq:", seq, 4)); | |
| 824 | |
| 825 (*sec->hash->update)(sec->hashcx, seq, 4); | |
| 826 | |
| 827 /* Get result */ | |
| 828 (*sec->hash->end)(sec->hashcx, result, &nout, sec->hash->length); | |
| 829 | |
| 830 return SECSuccess; | |
| 831 } | |
| 832 | |
| 833 /* | |
| 834 ** Maximum transmission amounts. These are tiny bit smaller than they | |
| 835 ** need to be (they account for the MAC length plus some padding), | |
| 836 ** assuming the MAC is 16 bytes long and the padding is a max of 7 bytes | |
| 837 ** long. This gives an additional 9 bytes of slop to work within. | |
| 838 */ | |
| 839 #define MAX_STREAM_CYPHER_LEN 0x7fe0 | |
| 840 #define MAX_BLOCK_CYPHER_LEN 0x3fe0 | |
| 841 | |
| 842 /* | |
| 843 ** Send some data in the clear. | |
| 844 ** Package up data with the length header and send it. | |
| 845 ** | |
| 846 ** Return count of bytes successfully written, or negative number (failure). | |
| 847 */ | |
| 848 static PRInt32 | |
| 849 ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) | |
| 850 { | |
| 851 PRUint8 * out; | |
| 852 int rv; | |
| 853 int amount; | |
| 854 int count = 0; | |
| 855 | |
| 856 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); | |
| 857 | |
| 858 SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear", | |
| 859 SSL_GETPID(), ss->fd, len)); | |
| 860 PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len)); | |
| 861 | |
| 862 while (len) { | |
| 863 amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN ); | |
| 864 if (amount + 2 > ss->sec.writeBuf.space) { | |
| 865 rv = sslBuffer_Grow(&ss->sec.writeBuf, amount + 2); | |
| 866 if (rv != SECSuccess) { | |
| 867 count = rv; | |
| 868 break; | |
| 869 } | |
| 870 } | |
| 871 out = ss->sec.writeBuf.buf; | |
| 872 | |
| 873 /* | |
| 874 ** Construct message. | |
| 875 */ | |
| 876 out[0] = 0x80 | MSB(amount); | |
| 877 out[1] = LSB(amount); | |
| 878 PORT_Memcpy(&out[2], in, amount); | |
| 879 | |
| 880 /* Now send the data */ | |
| 881 rv = ssl_DefSend(ss, out, amount + 2, flags & ~ssl_SEND_FLAG_MASK); | |
| 882 if (rv < 0) { | |
| 883 if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) { | |
| 884 rv = 0; | |
| 885 } else { | |
| 886 /* Return short write if some data already went out... */ | |
| 887 if (count == 0) | |
| 888 count = rv; | |
| 889 break; | |
| 890 } | |
| 891 } | |
| 892 | |
| 893 if ((unsigned)rv < (amount + 2)) { | |
| 894 /* Short write. Save the data and return. */ | |
| 895 if (ssl_SaveWriteData(ss, out + rv, amount + 2 - rv) | |
| 896 == SECFailure) { | |
| 897 count = SECFailure; | |
| 898 } else { | |
| 899 count += amount; | |
| 900 ss->sec.sendSequence++; | |
| 901 } | |
| 902 break; | |
| 903 } | |
| 904 | |
| 905 ss->sec.sendSequence++; | |
| 906 in += amount; | |
| 907 count += amount; | |
| 908 len -= amount; | |
| 909 } | |
| 910 | |
| 911 return count; | |
| 912 } | |
| 913 | |
| 914 /* | |
| 915 ** Send some data, when using a stream cipher. Stream ciphers have a | |
| 916 ** block size of 1. Package up the data with the length header | |
| 917 ** and send it. | |
| 918 */ | |
| 919 static PRInt32 | |
| 920 ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) | |
| 921 { | |
| 922 PRUint8 * out; | |
| 923 int rv; | |
| 924 int count = 0; | |
| 925 | |
| 926 int amount; | |
| 927 PRUint8 macLen; | |
| 928 int nout; | |
| 929 int buflen; | |
| 930 | |
| 931 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); | |
| 932 | |
| 933 SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher", | |
| 934 SSL_GETPID(), ss->fd, len)); | |
| 935 PRINT_BUF(50, (ss, "clear data:", (PRUint8*) in, len)); | |
| 936 | |
| 937 while (len) { | |
| 938 ssl_GetSpecReadLock(ss); /*************************************/ | |
| 939 | |
| 940 macLen = ss->sec.hash->length; | |
| 941 amount = PR_MIN( len, MAX_STREAM_CYPHER_LEN ); | |
| 942 buflen = amount + 2 + macLen; | |
| 943 if (buflen > ss->sec.writeBuf.space) { | |
| 944 rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen); | |
| 945 if (rv != SECSuccess) { | |
| 946 goto loser; | |
| 947 } | |
| 948 } | |
| 949 out = ss->sec.writeBuf.buf; | |
| 950 nout = amount + macLen; | |
| 951 out[0] = 0x80 | MSB(nout); | |
| 952 out[1] = LSB(nout); | |
| 953 | |
| 954 /* Calculate MAC */ | |
| 955 rv = ssl2_CalcMAC(out+2, /* put MAC here */ | |
| 956 &ss->sec, | |
| 957 in, amount, /* input addr & length */ | |
| 958 0); /* no padding */ | |
| 959 if (rv != SECSuccess) | |
| 960 goto loser; | |
| 961 | |
| 962 /* Encrypt MAC */ | |
| 963 rv = (*ss->sec.enc)(ss->sec.writecx, out+2, &nout, macLen, out+2, macLen
); | |
| 964 if (rv) goto loser; | |
| 965 | |
| 966 /* Encrypt data from caller */ | |
| 967 rv = (*ss->sec.enc)(ss->sec.writecx, out+2+macLen, &nout, amount, in, am
ount); | |
| 968 if (rv) goto loser; | |
| 969 | |
| 970 ssl_ReleaseSpecReadLock(ss); /*************************************/ | |
| 971 | |
| 972 PRINT_BUF(50, (ss, "encrypted data:", out, buflen)); | |
| 973 | |
| 974 rv = ssl_DefSend(ss, out, buflen, flags & ~ssl_SEND_FLAG_MASK); | |
| 975 if (rv < 0) { | |
| 976 if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) { | |
| 977 SSL_TRC(50, ("%d: SSL[%d]: send stream would block, " | |
| 978 "saving data", SSL_GETPID(), ss->fd)); | |
| 979 rv = 0; | |
| 980 } else { | |
| 981 SSL_TRC(10, ("%d: SSL[%d]: send stream error %d", | |
| 982 SSL_GETPID(), ss->fd, PORT_GetError())); | |
| 983 /* Return short write if some data already went out... */ | |
| 984 if (count == 0) | |
| 985 count = rv; | |
| 986 goto done; | |
| 987 } | |
| 988 } | |
| 989 | |
| 990 if ((unsigned)rv < buflen) { | |
| 991 /* Short write. Save the data and return. */ | |
| 992 if (ssl_SaveWriteData(ss, out + rv, buflen - rv) == SECFailure) { | |
| 993 count = SECFailure; | |
| 994 } else { | |
| 995 count += amount; | |
| 996 ss->sec.sendSequence++; | |
| 997 } | |
| 998 goto done; | |
| 999 } | |
| 1000 | |
| 1001 ss->sec.sendSequence++; | |
| 1002 in += amount; | |
| 1003 count += amount; | |
| 1004 len -= amount; | |
| 1005 } | |
| 1006 | |
| 1007 done: | |
| 1008 return count; | |
| 1009 | |
| 1010 loser: | |
| 1011 ssl_ReleaseSpecReadLock(ss); | |
| 1012 return SECFailure; | |
| 1013 } | |
| 1014 | |
| 1015 /* | |
| 1016 ** Send some data, when using a block cipher. Package up the data with | |
| 1017 ** the length header and send it. | |
| 1018 */ | |
| 1019 /* XXX assumes blocksize is > 7 */ | |
| 1020 static PRInt32 | |
| 1021 ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) | |
| 1022 { | |
| 1023 PRUint8 * out; /* begining of output buffer. */ | |
| 1024 PRUint8 * op; /* next output byte goes here. */ | |
| 1025 int rv; /* value from funcs we called. */ | |
| 1026 int count = 0; /* this function's return value. */ | |
| 1027 | |
| 1028 unsigned int hlen; /* output record hdr len, 2 or 3 */ | |
| 1029 unsigned int macLen; /* MAC is this many bytes long. */ | |
| 1030 int amount; /* of plaintext to go in record. */ | |
| 1031 unsigned int padding; /* add this many padding byte. */ | |
| 1032 int nout; /* ciphertext size after header. */ | |
| 1033 int buflen; /* size of generated record. */ | |
| 1034 | |
| 1035 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); | |
| 1036 | |
| 1037 SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher", | |
| 1038 SSL_GETPID(), ss->fd, len)); | |
| 1039 PRINT_BUF(50, (ss, "clear data:", in, len)); | |
| 1040 | |
| 1041 while (len) { | |
| 1042 ssl_GetSpecReadLock(ss); /*************************************/ | |
| 1043 | |
| 1044 macLen = ss->sec.hash->length; | |
| 1045 /* Figure out how much to send, including mac and padding */ | |
| 1046 amount = PR_MIN( len, MAX_BLOCK_CYPHER_LEN ); | |
| 1047 nout = amount + macLen; | |
| 1048 padding = nout & (ss->sec.blockSize - 1); | |
| 1049 if (padding) { | |
| 1050 hlen = 3; | |
| 1051 padding = ss->sec.blockSize - padding; | |
| 1052 nout += padding; | |
| 1053 } else { | |
| 1054 hlen = 2; | |
| 1055 } | |
| 1056 buflen = hlen + nout; | |
| 1057 if (buflen > ss->sec.writeBuf.space) { | |
| 1058 rv = sslBuffer_Grow(&ss->sec.writeBuf, buflen); | |
| 1059 if (rv != SECSuccess) { | |
| 1060 goto loser; | |
| 1061 } | |
| 1062 } | |
| 1063 out = ss->sec.writeBuf.buf; | |
| 1064 | |
| 1065 /* Construct header */ | |
| 1066 op = out; | |
| 1067 if (padding) { | |
| 1068 *op++ = MSB(nout); | |
| 1069 *op++ = LSB(nout); | |
| 1070 *op++ = padding; | |
| 1071 } else { | |
| 1072 *op++ = 0x80 | MSB(nout); | |
| 1073 *op++ = LSB(nout); | |
| 1074 } | |
| 1075 | |
| 1076 /* Calculate MAC */ | |
| 1077 rv = ssl2_CalcMAC(op, /* MAC goes here. */ | |
| 1078 &ss->sec, | |
| 1079 in, amount, /* intput addr, len */ | |
| 1080 padding); | |
| 1081 if (rv != SECSuccess) | |
| 1082 goto loser; | |
| 1083 op += macLen; | |
| 1084 | |
| 1085 /* Copy in the input data */ | |
| 1086 /* XXX could eliminate the copy by folding it into the encryption */ | |
| 1087 PORT_Memcpy(op, in, amount); | |
| 1088 op += amount; | |
| 1089 if (padding) { | |
| 1090 PORT_Memset(op, padding, padding); | |
| 1091 op += padding; | |
| 1092 } | |
| 1093 | |
| 1094 /* Encrypt result */ | |
| 1095 rv = (*ss->sec.enc)(ss->sec.writecx, out+hlen, &nout, buflen-hlen, | |
| 1096 out+hlen, op - (out + hlen)); | |
| 1097 if (rv) | |
| 1098 goto loser; | |
| 1099 | |
| 1100 ssl_ReleaseSpecReadLock(ss); /*************************************/ | |
| 1101 | |
| 1102 PRINT_BUF(50, (ss, "final xmit data:", out, op - out)); | |
| 1103 | |
| 1104 rv = ssl_DefSend(ss, out, op - out, flags & ~ssl_SEND_FLAG_MASK); | |
| 1105 if (rv < 0) { | |
| 1106 if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) { | |
| 1107 rv = 0; | |
| 1108 } else { | |
| 1109 SSL_TRC(10, ("%d: SSL[%d]: send block error %d", | |
| 1110 SSL_GETPID(), ss->fd, PORT_GetError())); | |
| 1111 /* Return short write if some data already went out... */ | |
| 1112 if (count == 0) | |
| 1113 count = rv; | |
| 1114 goto done; | |
| 1115 } | |
| 1116 } | |
| 1117 | |
| 1118 if (rv < (op - out)) { | |
| 1119 /* Short write. Save the data and return. */ | |
| 1120 if (ssl_SaveWriteData(ss, out + rv, op - out - rv) == SECFailure) { | |
| 1121 count = SECFailure; | |
| 1122 } else { | |
| 1123 count += amount; | |
| 1124 ss->sec.sendSequence++; | |
| 1125 } | |
| 1126 goto done; | |
| 1127 } | |
| 1128 | |
| 1129 ss->sec.sendSequence++; | |
| 1130 in += amount; | |
| 1131 count += amount; | |
| 1132 len -= amount; | |
| 1133 } | |
| 1134 | |
| 1135 done: | |
| 1136 return count; | |
| 1137 | |
| 1138 loser: | |
| 1139 ssl_ReleaseSpecReadLock(ss); | |
| 1140 return SECFailure; | |
| 1141 } | |
| 1142 | |
| 1143 /* | |
| 1144 ** Called from: ssl2_HandleServerHelloMessage, | |
| 1145 ** ssl2_HandleClientSessionKeyMessage, | |
| 1146 ** ssl2_HandleClientHelloMessage, | |
| 1147 ** | |
| 1148 */ | |
| 1149 static void | |
| 1150 ssl2_UseEncryptedSendFunc(sslSocket *ss) | |
| 1151 { | |
| 1152 ssl_GetXmitBufLock(ss); | |
| 1153 PORT_Assert(ss->sec.hashcx != 0); | |
| 1154 | |
| 1155 ss->gs.encrypted = 1; | |
| 1156 ss->sec.send = (ss->sec.blockSize > 1) ? ssl2_SendBlock : ssl2_SendStream; | |
| 1157 ssl_ReleaseXmitBufLock(ss); | |
| 1158 } | |
| 1159 | |
| 1160 /* Called while initializing socket in ssl_CreateSecurityInfo(). | |
| 1161 ** This function allows us to keep the name of ssl2_SendClear static. | |
| 1162 */ | |
| 1163 void | |
| 1164 ssl2_UseClearSendFunc(sslSocket *ss) | |
| 1165 { | |
| 1166 ss->sec.send = ssl2_SendClear; | |
| 1167 } | |
| 1168 | |
| 1169 /************************************************************************ | |
| 1170 ** END of Send functions. * | |
| 1171 *************************************************************************/ | |
| 1172 | |
| 1173 /*********************************************************************** | |
| 1174 * For SSL3, this gathers in and handles records/messages until either | |
| 1175 * the handshake is complete or application data is available. | |
| 1176 * | |
| 1177 * For SSL2, this gathers in only the next SSLV2 record. | |
| 1178 * | |
| 1179 * Called from ssl_Do1stHandshake() via function pointer ss->handshake. | |
| 1180 * Caller must hold handshake lock. | |
| 1181 * This function acquires and releases the RecvBufLock. | |
| 1182 * | |
| 1183 * returns SECSuccess for success. | |
| 1184 * returns SECWouldBlock when that value is returned by ssl2_GatherRecord() or | |
| 1185 * ssl3_GatherCompleteHandshake(). | |
| 1186 * returns SECFailure on all other errors. | |
| 1187 * | |
| 1188 * The gather functions called by ssl_GatherRecord1stHandshake are expected | |
| 1189 * to return values interpreted as follows: | |
| 1190 * 1 : the function completed without error. | |
| 1191 * 0 : the function read EOF. | |
| 1192 * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | |
| 1193 * -2 : the function wants ssl_GatherRecord1stHandshake to be called again | |
| 1194 * immediately, by ssl_Do1stHandshake. | |
| 1195 * | |
| 1196 * This code is similar to, and easily confused with, DoRecv() in sslsecur.c | |
| 1197 * | |
| 1198 * This function is called from ssl_Do1stHandshake(). | |
| 1199 * The following functions put ssl_GatherRecord1stHandshake into ss->handshake: | |
| 1200 * ssl2_HandleMessage | |
| 1201 * ssl2_HandleVerifyMessage | |
| 1202 * ssl2_HandleServerHelloMessage | |
| 1203 * ssl2_BeginClientHandshake | |
| 1204 * ssl2_HandleClientSessionKeyMessage | |
| 1205 * ssl3_RestartHandshakeAfterCertReq | |
| 1206 * ssl3_RestartHandshakeAfterServerCert | |
| 1207 * ssl2_HandleClientHelloMessage | |
| 1208 * ssl2_BeginServerHandshake | |
| 1209 */ | |
| 1210 SECStatus | |
| 1211 ssl_GatherRecord1stHandshake(sslSocket *ss) | |
| 1212 { | |
| 1213 int rv; | |
| 1214 | |
| 1215 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1216 | |
| 1217 ssl_GetRecvBufLock(ss); | |
| 1218 | |
| 1219 /* The special case DTLS logic is needed here because the SSL/TLS | |
| 1220 * version wants to auto-detect SSL2 vs. SSL3 on the initial handshake | |
| 1221 * (ss->version == 0) but with DTLS it gets confused, so we force the | |
| 1222 * SSL3 version. | |
| 1223 */ | |
| 1224 if ((ss->version >= SSL_LIBRARY_VERSION_3_0) || IS_DTLS(ss)) { | |
| 1225 /* Wait for handshake to complete, or application data to arrive. */ | |
| 1226 rv = ssl3_GatherCompleteHandshake(ss, 0); | |
| 1227 } else { | |
| 1228 /* See if we have a complete record */ | |
| 1229 rv = ssl2_GatherRecord(ss, 0); | |
| 1230 } | |
| 1231 SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d", | |
| 1232 SSL_GETPID(), ss->fd, rv)); | |
| 1233 | |
| 1234 ssl_ReleaseRecvBufLock(ss); | |
| 1235 | |
| 1236 if (rv <= 0) { | |
| 1237 if (rv == SECWouldBlock) { | |
| 1238 /* Progress is blocked waiting for callback completion. */ | |
| 1239 SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)", | |
| 1240 SSL_GETPID(), ss->fd, ss->gs.remainder)); | |
| 1241 return SECWouldBlock; | |
| 1242 } | |
| 1243 if (rv == 0) { | |
| 1244 /* EOF. Loser */ | |
| 1245 PORT_SetError(PR_END_OF_FILE_ERROR); | |
| 1246 } | |
| 1247 return SECFailure; /* rv is < 0 here. */ | |
| 1248 } | |
| 1249 | |
| 1250 SSL_TRC(10, ("%d: SSL[%d]: got handshake record of %d bytes", | |
| 1251 SSL_GETPID(), ss->fd, ss->gs.recordLen)); | |
| 1252 | |
| 1253 ss->handshake = 0; /* makes ssl_Do1stHandshake call ss->nextHandshake.*/ | |
| 1254 return SECSuccess; | |
| 1255 } | |
| 1256 | |
| 1257 /************************************************************************/ | |
| 1258 | |
| 1259 /* Called from ssl2_ServerSetupSessionCypher() | |
| 1260 * ssl2_ClientSetupSessionCypher() | |
| 1261 */ | |
| 1262 static SECStatus | |
| 1263 ssl2_FillInSID(sslSessionID * sid, | |
| 1264 int cipher, | |
| 1265 PRUint8 *keyData, | |
| 1266 int keyLen, | |
| 1267 PRUint8 *ca, | |
| 1268 int caLen, | |
| 1269 int keyBits, | |
| 1270 int secretKeyBits, | |
| 1271 SSLSignType authAlgorithm, | |
| 1272 PRUint32 authKeyBits, | |
| 1273 SSLKEAType keaType, | |
| 1274 PRUint32 keaKeyBits) | |
| 1275 { | |
| 1276 PORT_Assert(sid->references == 1); | |
| 1277 PORT_Assert(sid->cached == never_cached); | |
| 1278 PORT_Assert(sid->u.ssl2.masterKey.data == 0); | |
| 1279 PORT_Assert(sid->u.ssl2.cipherArg.data == 0); | |
| 1280 | |
| 1281 sid->version = SSL_LIBRARY_VERSION_2; | |
| 1282 | |
| 1283 sid->u.ssl2.cipherType = cipher; | |
| 1284 sid->u.ssl2.masterKey.data = (PRUint8*) PORT_Alloc(keyLen); | |
| 1285 if (!sid->u.ssl2.masterKey.data) { | |
| 1286 return SECFailure; | |
| 1287 } | |
| 1288 PORT_Memcpy(sid->u.ssl2.masterKey.data, keyData, keyLen); | |
| 1289 sid->u.ssl2.masterKey.len = keyLen; | |
| 1290 sid->u.ssl2.keyBits = keyBits; | |
| 1291 sid->u.ssl2.secretKeyBits = secretKeyBits; | |
| 1292 sid->authAlgorithm = authAlgorithm; | |
| 1293 sid->authKeyBits = authKeyBits; | |
| 1294 sid->keaType = keaType; | |
| 1295 sid->keaKeyBits = keaKeyBits; | |
| 1296 sid->lastAccessTime = sid->creationTime = ssl_Time(); | |
| 1297 sid->expirationTime = sid->creationTime + ssl_sid_timeout; | |
| 1298 | |
| 1299 if (caLen) { | |
| 1300 sid->u.ssl2.cipherArg.data = (PRUint8*) PORT_Alloc(caLen); | |
| 1301 if (!sid->u.ssl2.cipherArg.data) { | |
| 1302 return SECFailure; | |
| 1303 } | |
| 1304 sid->u.ssl2.cipherArg.len = caLen; | |
| 1305 PORT_Memcpy(sid->u.ssl2.cipherArg.data, ca, caLen); | |
| 1306 } | |
| 1307 return SECSuccess; | |
| 1308 } | |
| 1309 | |
| 1310 /* | |
| 1311 ** Construct session keys given the masterKey (tied to the session-id), | |
| 1312 ** the client's challenge and the server's nonce. | |
| 1313 ** | |
| 1314 ** Called from ssl2_CreateSessionCypher() <- | |
| 1315 */ | |
| 1316 static SECStatus | |
| 1317 ssl2_ProduceKeys(sslSocket * ss, | |
| 1318 SECItem * readKey, | |
| 1319 SECItem * writeKey, | |
| 1320 SECItem * masterKey, | |
| 1321 PRUint8 * challenge, | |
| 1322 PRUint8 * nonce, | |
| 1323 int cipherType) | |
| 1324 { | |
| 1325 PK11Context * cx = 0; | |
| 1326 unsigned nkm = 0; /* number of hashes to generate key mat. */ | |
| 1327 unsigned nkd = 0; /* size of readKey and writeKey. */ | |
| 1328 unsigned part; | |
| 1329 unsigned i; | |
| 1330 unsigned off; | |
| 1331 SECStatus rv; | |
| 1332 PRUint8 countChar; | |
| 1333 PRUint8 km[3*16]; /* buffer for key material. */ | |
| 1334 | |
| 1335 readKey->data = 0; | |
| 1336 writeKey->data = 0; | |
| 1337 | |
| 1338 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1339 | |
| 1340 rv = SECSuccess; | |
| 1341 cx = PK11_CreateDigestContext(SEC_OID_MD5); | |
| 1342 if (cx == NULL) { | |
| 1343 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); | |
| 1344 return SECFailure; | |
| 1345 } | |
| 1346 | |
| 1347 nkm = ssl_Specs[cipherType].nkm; | |
| 1348 nkd = ssl_Specs[cipherType].nkd; | |
| 1349 | |
| 1350 readKey->data = (PRUint8*) PORT_Alloc(nkd); | |
| 1351 if (!readKey->data) | |
| 1352 goto loser; | |
| 1353 readKey->len = nkd; | |
| 1354 | |
| 1355 writeKey->data = (PRUint8*) PORT_Alloc(nkd); | |
| 1356 if (!writeKey->data) | |
| 1357 goto loser; | |
| 1358 writeKey->len = nkd; | |
| 1359 | |
| 1360 /* Produce key material */ | |
| 1361 countChar = '0'; | |
| 1362 for (i = 0, off = 0; i < nkm; i++, off += 16) { | |
| 1363 rv = PK11_DigestBegin(cx); | |
| 1364 rv |= PK11_DigestOp(cx, masterKey->data, masterKey->len); | |
| 1365 rv |= PK11_DigestOp(cx, &countChar, 1); | |
| 1366 rv |= PK11_DigestOp(cx, challenge, SSL_CHALLENGE_BYTES); | |
| 1367 rv |= PK11_DigestOp(cx, nonce, SSL_CONNECTIONID_BYTES); | |
| 1368 rv |= PK11_DigestFinal(cx, km+off, &part, MD5_LENGTH); | |
| 1369 if (rv != SECSuccess) { | |
| 1370 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); | |
| 1371 rv = SECFailure; | |
| 1372 goto loser; | |
| 1373 } | |
| 1374 countChar++; | |
| 1375 } | |
| 1376 | |
| 1377 /* Produce keys */ | |
| 1378 PORT_Memcpy(readKey->data, km, nkd); | |
| 1379 PORT_Memcpy(writeKey->data, km + nkd, nkd); | |
| 1380 | |
| 1381 loser: | |
| 1382 PK11_DestroyContext(cx, PR_TRUE); | |
| 1383 return rv; | |
| 1384 } | |
| 1385 | |
| 1386 /* Called from ssl2_ServerSetupSessionCypher() | |
| 1387 ** <- ssl2_HandleClientSessionKeyMessage() | |
| 1388 ** <- ssl2_HandleClientHelloMessage() | |
| 1389 ** and from ssl2_ClientSetupSessionCypher() | |
| 1390 ** <- ssl2_HandleServerHelloMessage() | |
| 1391 */ | |
| 1392 static SECStatus | |
| 1393 ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient) | |
| 1394 { | |
| 1395 SECItem * rk = NULL; | |
| 1396 SECItem * wk = NULL; | |
| 1397 SECItem * param; | |
| 1398 SECStatus rv; | |
| 1399 int cipherType = sid->u.ssl2.cipherType; | |
| 1400 PK11SlotInfo * slot = NULL; | |
| 1401 CK_MECHANISM_TYPE mechanism; | |
| 1402 SECItem readKey; | |
| 1403 SECItem writeKey; | |
| 1404 | |
| 1405 void *readcx = 0; | |
| 1406 void *writecx = 0; | |
| 1407 readKey.data = 0; | |
| 1408 writeKey.data = 0; | |
| 1409 | |
| 1410 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1411 if (ss->sec.ci.sid == 0) | |
| 1412 goto sec_loser; /* don't crash if asserts are off */ | |
| 1413 | |
| 1414 /* Trying to cut down on all these switch statements that should be tables. | |
| 1415 * So, test cipherType once, here, and then use tables below. | |
| 1416 */ | |
| 1417 switch (cipherType) { | |
| 1418 case SSL_CK_RC4_128_EXPORT40_WITH_MD5: | |
| 1419 case SSL_CK_RC4_128_WITH_MD5: | |
| 1420 case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: | |
| 1421 case SSL_CK_RC2_128_CBC_WITH_MD5: | |
| 1422 case SSL_CK_DES_64_CBC_WITH_MD5: | |
| 1423 case SSL_CK_DES_192_EDE3_CBC_WITH_MD5: | |
| 1424 break; | |
| 1425 | |
| 1426 default: | |
| 1427 SSL_DBG(("%d: SSL[%d]: ssl2_CreateSessionCypher: unknown cipher=%d", | |
| 1428 SSL_GETPID(), ss->fd, cipherType)); | |
| 1429 PORT_SetError(isClient ? SSL_ERROR_BAD_SERVER : SSL_ERROR_BAD_CLIENT); | |
| 1430 goto sec_loser; | |
| 1431 } | |
| 1432 | |
| 1433 rk = isClient ? &readKey : &writeKey; | |
| 1434 wk = isClient ? &writeKey : &readKey; | |
| 1435 | |
| 1436 /* Produce the keys for this session */ | |
| 1437 rv = ssl2_ProduceKeys(ss, &readKey, &writeKey, &sid->u.ssl2.masterKey, | |
| 1438 ss->sec.ci.clientChallenge, ss->sec.ci.connectionID, | |
| 1439 cipherType); | |
| 1440 if (rv != SECSuccess) | |
| 1441 goto loser; | |
| 1442 PRINT_BUF(7, (ss, "Session read-key: ", rk->data, rk->len)); | |
| 1443 PRINT_BUF(7, (ss, "Session write-key: ", wk->data, wk->len)); | |
| 1444 | |
| 1445 PORT_Memcpy(ss->sec.ci.readKey, readKey.data, readKey.len); | |
| 1446 PORT_Memcpy(ss->sec.ci.writeKey, writeKey.data, writeKey.len); | |
| 1447 ss->sec.ci.keySize = readKey.len; | |
| 1448 | |
| 1449 /* Setup the MAC */ | |
| 1450 rv = ssl2_CreateMAC(&ss->sec, rk, wk, cipherType); | |
| 1451 if (rv != SECSuccess) | |
| 1452 goto loser; | |
| 1453 | |
| 1454 /* First create the session key object */ | |
| 1455 SSL_TRC(3, ("%d: SSL[%d]: using %s", SSL_GETPID(), ss->fd, | |
| 1456 ssl_cipherName[cipherType])); | |
| 1457 | |
| 1458 | |
| 1459 mechanism = ssl_Specs[cipherType].mechanism; | |
| 1460 | |
| 1461 /* set destructer before we call loser... */ | |
| 1462 ss->sec.destroy = (void (*)(void*, PRBool)) PK11_DestroyContext; | |
| 1463 slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg); | |
| 1464 if (slot == NULL) | |
| 1465 goto loser; | |
| 1466 | |
| 1467 param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg); | |
| 1468 if (param == NULL) | |
| 1469 goto loser; | |
| 1470 readcx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap, | |
| 1471 CKA_DECRYPT, rk, param, | |
| 1472 ss->pkcs11PinArg); | |
| 1473 SECITEM_FreeItem(param, PR_TRUE); | |
| 1474 if (readcx == NULL) | |
| 1475 goto loser; | |
| 1476 | |
| 1477 /* build the client context */ | |
| 1478 param = PK11_ParamFromIV(mechanism, &sid->u.ssl2.cipherArg); | |
| 1479 if (param == NULL) | |
| 1480 goto loser; | |
| 1481 writecx = PK11_CreateContextByRawKey(slot, mechanism, PK11_OriginUnwrap, | |
| 1482 CKA_ENCRYPT, wk, param, | |
| 1483 ss->pkcs11PinArg); | |
| 1484 SECITEM_FreeItem(param,PR_TRUE); | |
| 1485 if (writecx == NULL) | |
| 1486 goto loser; | |
| 1487 PK11_FreeSlot(slot); | |
| 1488 | |
| 1489 rv = SECSuccess; | |
| 1490 ss->sec.enc = (SSLCipher) PK11_CipherOp; | |
| 1491 ss->sec.dec = (SSLCipher) PK11_CipherOp; | |
| 1492 ss->sec.readcx = (void *) readcx; | |
| 1493 ss->sec.writecx = (void *) writecx; | |
| 1494 ss->sec.blockSize = ssl_Specs[cipherType].blockSize; | |
| 1495 ss->sec.blockShift = ssl_Specs[cipherType].blockShift; | |
| 1496 ss->sec.cipherType = sid->u.ssl2.cipherType; | |
| 1497 ss->sec.keyBits = sid->u.ssl2.keyBits; | |
| 1498 ss->sec.secretKeyBits = sid->u.ssl2.secretKeyBits; | |
| 1499 goto done; | |
| 1500 | |
| 1501 loser: | |
| 1502 if (ss->sec.destroy) { | |
| 1503 if (readcx) (*ss->sec.destroy)(readcx, PR_TRUE); | |
| 1504 if (writecx) (*ss->sec.destroy)(writecx, PR_TRUE); | |
| 1505 } | |
| 1506 ss->sec.destroy = NULL; | |
| 1507 if (slot) PK11_FreeSlot(slot); | |
| 1508 | |
| 1509 sec_loser: | |
| 1510 rv = SECFailure; | |
| 1511 | |
| 1512 done: | |
| 1513 if (rk) { | |
| 1514 SECITEM_ZfreeItem(rk, PR_FALSE); | |
| 1515 } | |
| 1516 if (wk) { | |
| 1517 SECITEM_ZfreeItem(wk, PR_FALSE); | |
| 1518 } | |
| 1519 return rv; | |
| 1520 } | |
| 1521 | |
| 1522 /* | |
| 1523 ** Setup the server ciphers given information from a CLIENT-MASTER-KEY | |
| 1524 ** message. | |
| 1525 ** "ss" pointer to the ssl-socket object | |
| 1526 ** "cipher" the cipher type to use | |
| 1527 ** "keyBits" the size of the final cipher key | |
| 1528 ** "ck" the clear-key data | |
| 1529 ** "ckLen" the number of bytes of clear-key data | |
| 1530 ** "ek" the encrypted-key data | |
| 1531 ** "ekLen" the number of bytes of encrypted-key data | |
| 1532 ** "ca" the cipher-arg data | |
| 1533 ** "caLen" the number of bytes of cipher-arg data | |
| 1534 ** | |
| 1535 ** The MASTER-KEY is constructed by first decrypting the encrypted-key | |
| 1536 ** data. This produces the SECRET-KEY-DATA. The MASTER-KEY is composed by | |
| 1537 ** concatenating the clear-key data with the SECRET-KEY-DATA. This code | |
| 1538 ** checks to make sure that the client didn't send us an improper amount | |
| 1539 ** of SECRET-KEY-DATA (it restricts the length of that data to match the | |
| 1540 ** spec). | |
| 1541 ** | |
| 1542 ** Called from ssl2_HandleClientSessionKeyMessage(). | |
| 1543 */ | |
| 1544 static SECStatus | |
| 1545 ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits, | |
| 1546 PRUint8 *ck, unsigned int ckLen, | |
| 1547 PRUint8 *ek, unsigned int ekLen, | |
| 1548 PRUint8 *ca, unsigned int caLen) | |
| 1549 { | |
| 1550 PRUint8 * dk = NULL; /* decrypted master key */ | |
| 1551 sslSessionID * sid; | |
| 1552 sslServerCerts * sc = ss->serverCerts + kt_rsa; | |
| 1553 PRUint8 * kbuf = 0; /* buffer for RSA decrypted data. */ | |
| 1554 unsigned int ddLen; /* length of RSA decrypted data in kbuf */ | |
| 1555 unsigned int keySize; | |
| 1556 unsigned int dkLen; /* decrypted key length in bytes */ | |
| 1557 int modulusLen; | |
| 1558 SECStatus rv; | |
| 1559 PRUint16 allowed; /* cipher kinds enabled and allowed by policy */ | |
| 1560 PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES]; | |
| 1561 | |
| 1562 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1563 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1564 PORT_Assert((sc->SERVERKEY != 0)); | |
| 1565 PORT_Assert((ss->sec.ci.sid != 0)); | |
| 1566 sid = ss->sec.ci.sid; | |
| 1567 | |
| 1568 /* Trying to cut down on all these switch statements that should be tables. | |
| 1569 * So, test cipherType once, here, and then use tables below. | |
| 1570 */ | |
| 1571 switch (cipher) { | |
| 1572 case SSL_CK_RC4_128_EXPORT40_WITH_MD5: | |
| 1573 case SSL_CK_RC4_128_WITH_MD5: | |
| 1574 case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: | |
| 1575 case SSL_CK_RC2_128_CBC_WITH_MD5: | |
| 1576 case SSL_CK_DES_64_CBC_WITH_MD5: | |
| 1577 case SSL_CK_DES_192_EDE3_CBC_WITH_MD5: | |
| 1578 break; | |
| 1579 | |
| 1580 default: | |
| 1581 SSL_DBG(("%d: SSL[%d]: ssl2_ServerSetupSessionCypher: unknown cipher=%d"
, | |
| 1582 SSL_GETPID(), ss->fd, cipher)); | |
| 1583 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1584 goto loser; | |
| 1585 } | |
| 1586 | |
| 1587 allowed = ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED; | |
| 1588 if (!(allowed & (1 << cipher))) { | |
| 1589 /* client chose a kind we don't allow! */ | |
| 1590 SSL_DBG(("%d: SSL[%d]: disallowed cipher=%d", | |
| 1591 SSL_GETPID(), ss->fd, cipher)); | |
| 1592 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1593 goto loser; | |
| 1594 } | |
| 1595 | |
| 1596 keySize = ssl_Specs[cipher].keyLen; | |
| 1597 if (keyBits != keySize * BPB) { | |
| 1598 SSL_DBG(("%d: SSL[%d]: invalid master secret key length=%d (bits)!", | |
| 1599 SSL_GETPID(), ss->fd, keyBits)); | |
| 1600 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1601 goto loser; | |
| 1602 } | |
| 1603 | |
| 1604 if (ckLen != ssl_Specs[cipher].pubLen) { | |
| 1605 SSL_DBG(("%d: SSL[%d]: invalid clear key length, ckLen=%d (bytes)!", | |
| 1606 SSL_GETPID(), ss->fd, ckLen)); | |
| 1607 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1608 goto loser; | |
| 1609 } | |
| 1610 | |
| 1611 if (caLen != ssl_Specs[cipher].ivLen) { | |
| 1612 SSL_DBG(("%d: SSL[%d]: invalid key args length, caLen=%d (bytes)!", | |
| 1613 SSL_GETPID(), ss->fd, caLen)); | |
| 1614 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1615 goto loser; | |
| 1616 } | |
| 1617 | |
| 1618 modulusLen = PK11_GetPrivateModulusLen(sc->SERVERKEY); | |
| 1619 if (modulusLen == -1) { | |
| 1620 /* XXX If the key is bad, then PK11_PubDecryptRaw will fail below. */ | |
| 1621 modulusLen = ekLen; | |
| 1622 } | |
| 1623 if (ekLen > modulusLen || ekLen + ckLen < keySize) { | |
| 1624 SSL_DBG(("%d: SSL[%d]: invalid encrypted key length, ekLen=%d (bytes)!", | |
| 1625 SSL_GETPID(), ss->fd, ekLen)); | |
| 1626 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1627 goto loser; | |
| 1628 } | |
| 1629 | |
| 1630 /* allocate the buffer to hold the decrypted portion of the key. */ | |
| 1631 kbuf = (PRUint8*)PORT_Alloc(modulusLen); | |
| 1632 if (!kbuf) { | |
| 1633 goto loser; | |
| 1634 } | |
| 1635 dkLen = keySize - ckLen; | |
| 1636 dk = kbuf + modulusLen - dkLen; | |
| 1637 | |
| 1638 /* Decrypt encrypted half of the key. | |
| 1639 ** NOTE: PK11_PubDecryptRaw will barf on a non-RSA key. This is | |
| 1640 ** desired behavior here. | |
| 1641 */ | |
| 1642 rv = PK11_PubDecryptRaw(sc->SERVERKEY, kbuf, &ddLen, modulusLen, ek, ekLen); | |
| 1643 if (rv != SECSuccess) | |
| 1644 goto hide_loser; | |
| 1645 | |
| 1646 /* Is the length of the decrypted data (ddLen) the expected value? */ | |
| 1647 if (modulusLen != ddLen) | |
| 1648 goto hide_loser; | |
| 1649 | |
| 1650 /* Cheaply verify that PKCS#1 was used to format the encryption block */ | |
| 1651 if ((kbuf[0] != 0x00) || (kbuf[1] != 0x02) || (dk[-1] != 0x00)) { | |
| 1652 SSL_DBG(("%d: SSL[%d]: strange encryption block", | |
| 1653 SSL_GETPID(), ss->fd)); | |
| 1654 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1655 goto hide_loser; | |
| 1656 } | |
| 1657 | |
| 1658 /* Make sure we're not subject to a version rollback attack. */ | |
| 1659 if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { | |
| 1660 static const PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03, | |
| 1661 0x03, 0x03, 0x03, 0x03 }; | |
| 1662 | |
| 1663 if (PORT_Memcmp(dk - 8 - 1, threes, 8) == 0) { | |
| 1664 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 1665 goto hide_loser; | |
| 1666 } | |
| 1667 } | |
| 1668 if (0) { | |
| 1669 hide_loser: | |
| 1670 /* Defense against the Bleichenbacher attack. | |
| 1671 * Provide the client with NO CLUES that the decrypted master key | |
| 1672 * was erroneous. Don't send any error messages. | |
| 1673 * Instead, Generate a completely bogus master key . | |
| 1674 */ | |
| 1675 PK11_GenerateRandom(dk, dkLen); | |
| 1676 } | |
| 1677 | |
| 1678 /* | |
| 1679 ** Construct master key out of the pieces. | |
| 1680 */ | |
| 1681 if (ckLen) { | |
| 1682 PORT_Memcpy(mkbuf, ck, ckLen); | |
| 1683 } | |
| 1684 PORT_Memcpy(mkbuf + ckLen, dk, dkLen); | |
| 1685 | |
| 1686 /* Fill in session-id */ | |
| 1687 rv = ssl2_FillInSID(sid, cipher, mkbuf, keySize, ca, caLen, | |
| 1688 keyBits, keyBits - (ckLen<<3), | |
| 1689 ss->sec.authAlgorithm, ss->sec.authKeyBits, | |
| 1690 ss->sec.keaType, ss->sec.keaKeyBits); | |
| 1691 if (rv != SECSuccess) { | |
| 1692 goto loser; | |
| 1693 } | |
| 1694 | |
| 1695 /* Create session ciphers */ | |
| 1696 rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE); | |
| 1697 if (rv != SECSuccess) { | |
| 1698 goto loser; | |
| 1699 } | |
| 1700 | |
| 1701 SSL_TRC(1, ("%d: SSL[%d]: server, using %s cipher, clear=%d total=%d", | |
| 1702 SSL_GETPID(), ss->fd, ssl_cipherName[cipher], | |
| 1703 ckLen<<3, keySize<<3)); | |
| 1704 rv = SECSuccess; | |
| 1705 goto done; | |
| 1706 | |
| 1707 loser: | |
| 1708 rv = SECFailure; | |
| 1709 | |
| 1710 done: | |
| 1711 PORT_Free(kbuf); | |
| 1712 return rv; | |
| 1713 } | |
| 1714 | |
| 1715 /************************************************************************/ | |
| 1716 | |
| 1717 /* | |
| 1718 ** Rewrite the incoming cipher specs, comparing to list of specs we support, | |
| 1719 ** (ss->cipherSpecs) and eliminating anything we don't support | |
| 1720 ** | |
| 1721 * Note: Our list may contain SSL v3 ciphers. | |
| 1722 * We MUST NOT match on any of those. | |
| 1723 * Fortunately, this is easy to detect because SSLv3 ciphers have zero | |
| 1724 * in the first byte, and none of the SSLv2 ciphers do. | |
| 1725 * | |
| 1726 * Called from ssl2_HandleClientHelloMessage(). | |
| 1727 * Returns the number of bytes of "qualified cipher specs", | |
| 1728 * which is typically a multiple of 3, but will be zero if there are none. | |
| 1729 */ | |
| 1730 static int | |
| 1731 ssl2_QualifyCypherSpecs(sslSocket *ss, | |
| 1732 PRUint8 * cs, /* cipher specs in client hello msg. */ | |
| 1733 int csLen) | |
| 1734 { | |
| 1735 PRUint8 * ms; | |
| 1736 PRUint8 * hs; | |
| 1737 PRUint8 * qs; | |
| 1738 int mc; | |
| 1739 int hc; | |
| 1740 PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3]; | |
| 1741 | |
| 1742 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1743 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1744 | |
| 1745 if (!ss->cipherSpecs) { | |
| 1746 SECStatus rv = ssl2_ConstructCipherSpecs(ss); | |
| 1747 if (rv != SECSuccess || !ss->cipherSpecs) | |
| 1748 return 0; | |
| 1749 } | |
| 1750 | |
| 1751 PRINT_BUF(10, (ss, "specs from client:", cs, csLen)); | |
| 1752 qs = qualifiedSpecs; | |
| 1753 ms = ss->cipherSpecs; | |
| 1754 for (mc = ss->sizeCipherSpecs; mc > 0; mc -= 3, ms += 3) { | |
| 1755 if (ms[0] == 0) | |
| 1756 continue; | |
| 1757 for (hs = cs, hc = csLen; hc > 0; hs += 3, hc -= 3) { | |
| 1758 if ((hs[0] == ms[0]) && | |
| 1759 (hs[1] == ms[1]) && | |
| 1760 (hs[2] == ms[2])) { | |
| 1761 /* Copy this cipher spec into the "keep" section */ | |
| 1762 qs[0] = hs[0]; | |
| 1763 qs[1] = hs[1]; | |
| 1764 qs[2] = hs[2]; | |
| 1765 qs += 3; | |
| 1766 break; | |
| 1767 } | |
| 1768 } | |
| 1769 } | |
| 1770 hc = qs - qualifiedSpecs; | |
| 1771 PRINT_BUF(10, (ss, "qualified specs from client:", qualifiedSpecs, hc)); | |
| 1772 PORT_Memcpy(cs, qualifiedSpecs, hc); | |
| 1773 return hc; | |
| 1774 } | |
| 1775 | |
| 1776 /* | |
| 1777 ** Pick the best cipher we can find, given the array of server cipher | |
| 1778 ** specs. Returns cipher number (e.g. SSL_CK_*), or -1 for no overlap. | |
| 1779 ** If successful, stores the master key size (bytes) in *pKeyLen. | |
| 1780 ** | |
| 1781 ** This is correct only for the client side, but presently | |
| 1782 ** this function is only called from | |
| 1783 ** ssl2_ClientSetupSessionCypher() <- ssl2_HandleServerHelloMessage() | |
| 1784 ** | |
| 1785 ** Note that most servers only return a single cipher suite in their | |
| 1786 ** ServerHello messages. So, the code below for finding the "best" cipher | |
| 1787 ** suite usually has only one choice. The client and server should send | |
| 1788 ** their cipher suite lists sorted in descending order by preference. | |
| 1789 */ | |
| 1790 static int | |
| 1791 ssl2_ChooseSessionCypher(sslSocket *ss, | |
| 1792 int hc, /* number of cs's in hs. */ | |
| 1793 PRUint8 * hs, /* server hello's cipher suites. */ | |
| 1794 int * pKeyLen) /* out: sym key size in bytes. */ | |
| 1795 { | |
| 1796 PRUint8 * ms; | |
| 1797 unsigned int i; | |
| 1798 int bestKeySize; | |
| 1799 int bestRealKeySize; | |
| 1800 int bestCypher; | |
| 1801 int keySize; | |
| 1802 int realKeySize; | |
| 1803 PRUint8 * ohs = hs; | |
| 1804 const PRUint8 * preferred; | |
| 1805 static const PRUint8 noneSuch[3] = { 0, 0, 0 }; | |
| 1806 | |
| 1807 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 1808 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1809 | |
| 1810 if (!ss->cipherSpecs) { | |
| 1811 SECStatus rv = ssl2_ConstructCipherSpecs(ss); | |
| 1812 if (rv != SECSuccess || !ss->cipherSpecs) | |
| 1813 goto loser; | |
| 1814 } | |
| 1815 | |
| 1816 if (!ss->preferredCipher) { | |
| 1817 unsigned int allowed = ss->allowedByPolicy & ss->chosenPreference & | |
| 1818 SSL_CB_IMPLEMENTED; | |
| 1819 if (allowed) { | |
| 1820 preferred = implementedCipherSuites; | |
| 1821 for (i = ssl2_NUM_SUITES_IMPLEMENTED; i > 0; --i) { | |
| 1822 if (0 != (allowed & (1U << preferred[0]))) { | |
| 1823 ss->preferredCipher = preferred; | |
| 1824 break; | |
| 1825 } | |
| 1826 preferred += 3; | |
| 1827 } | |
| 1828 } | |
| 1829 } | |
| 1830 preferred = ss->preferredCipher ? ss->preferredCipher : noneSuch; | |
| 1831 /* | |
| 1832 ** Scan list of ciphers received from peer and look for a match in | |
| 1833 ** our list. | |
| 1834 * Note: Our list may contain SSL v3 ciphers. | |
| 1835 * We MUST NOT match on any of those. | |
| 1836 * Fortunately, this is easy to detect because SSLv3 ciphers have zero | |
| 1837 * in the first byte, and none of the SSLv2 ciphers do. | |
| 1838 */ | |
| 1839 bestKeySize = bestRealKeySize = 0; | |
| 1840 bestCypher = -1; | |
| 1841 while (--hc >= 0) { | |
| 1842 for (i = 0, ms = ss->cipherSpecs; i < ss->sizeCipherSpecs; i += 3, ms +=
3) { | |
| 1843 if ((hs[0] == preferred[0]) && | |
| 1844 (hs[1] == preferred[1]) && | |
| 1845 (hs[2] == preferred[2]) && | |
| 1846 hs[0] != 0) { | |
| 1847 /* Pick this cipher immediately! */ | |
| 1848 *pKeyLen = (((hs[1] << 8) | hs[2]) + 7) >> 3; | |
| 1849 return hs[0]; | |
| 1850 } | |
| 1851 if ((hs[0] == ms[0]) && (hs[1] == ms[1]) && (hs[2] == ms[2]) && | |
| 1852 hs[0] != 0) { | |
| 1853 /* Found a match */ | |
| 1854 | |
| 1855 /* Use secret keySize to determine which cipher is best */ | |
| 1856 realKeySize = (hs[1] << 8) | hs[2]; | |
| 1857 switch (hs[0]) { | |
| 1858 case SSL_CK_RC4_128_EXPORT40_WITH_MD5: | |
| 1859 case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: | |
| 1860 keySize = 40; | |
| 1861 break; | |
| 1862 default: | |
| 1863 keySize = realKeySize; | |
| 1864 break; | |
| 1865 } | |
| 1866 if (keySize > bestKeySize) { | |
| 1867 bestCypher = hs[0]; | |
| 1868 bestKeySize = keySize; | |
| 1869 bestRealKeySize = realKeySize; | |
| 1870 } | |
| 1871 } | |
| 1872 } | |
| 1873 hs += 3; | |
| 1874 } | |
| 1875 if (bestCypher < 0) { | |
| 1876 /* | |
| 1877 ** No overlap between server and client. Re-examine server list | |
| 1878 ** to see what kind of ciphers it does support so that we can set | |
| 1879 ** the error code appropriately. | |
| 1880 */ | |
| 1881 if ((ohs[0] == SSL_CK_RC4_128_WITH_MD5) || | |
| 1882 (ohs[0] == SSL_CK_RC2_128_CBC_WITH_MD5)) { | |
| 1883 PORT_SetError(SSL_ERROR_US_ONLY_SERVER); | |
| 1884 } else if ((ohs[0] == SSL_CK_RC4_128_EXPORT40_WITH_MD5) || | |
| 1885 (ohs[0] == SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5)) { | |
| 1886 PORT_SetError(SSL_ERROR_EXPORT_ONLY_SERVER); | |
| 1887 } else { | |
| 1888 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 1889 } | |
| 1890 SSL_DBG(("%d: SSL[%d]: no cipher overlap", SSL_GETPID(), ss->fd)); | |
| 1891 goto loser; | |
| 1892 } | |
| 1893 *pKeyLen = (bestRealKeySize + 7) >> 3; | |
| 1894 return bestCypher; | |
| 1895 | |
| 1896 loser: | |
| 1897 return -1; | |
| 1898 } | |
| 1899 | |
| 1900 static SECStatus | |
| 1901 ssl2_ClientHandleServerCert(sslSocket *ss, PRUint8 *certData, int certLen) | |
| 1902 { | |
| 1903 CERTCertificate *cert = NULL; | |
| 1904 SECItem certItem; | |
| 1905 | |
| 1906 certItem.data = certData; | |
| 1907 certItem.len = certLen; | |
| 1908 | |
| 1909 /* decode the certificate */ | |
| 1910 cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, | |
| 1911 PR_FALSE, PR_TRUE); | |
| 1912 | |
| 1913 if (cert == NULL) { | |
| 1914 SSL_DBG(("%d: SSL[%d]: decode of server certificate fails", | |
| 1915 SSL_GETPID(), ss->fd)); | |
| 1916 PORT_SetError(SSL_ERROR_BAD_CERTIFICATE); | |
| 1917 return SECFailure; | |
| 1918 } | |
| 1919 | |
| 1920 #ifdef TRACE | |
| 1921 { | |
| 1922 if (ssl_trace >= 1) { | |
| 1923 char *issuer; | |
| 1924 char *subject; | |
| 1925 issuer = CERT_NameToAscii(&cert->issuer); | |
| 1926 subject = CERT_NameToAscii(&cert->subject); | |
| 1927 SSL_TRC(1,("%d: server certificate issuer: '%s'", | |
| 1928 SSL_GETPID(), issuer ? issuer : "OOPS")); | |
| 1929 SSL_TRC(1,("%d: server name: '%s'", | |
| 1930 SSL_GETPID(), subject ? subject : "OOPS")); | |
| 1931 PORT_Free(issuer); | |
| 1932 PORT_Free(subject); | |
| 1933 } | |
| 1934 } | |
| 1935 #endif | |
| 1936 | |
| 1937 ss->sec.peerCert = cert; | |
| 1938 return SECSuccess; | |
| 1939 } | |
| 1940 | |
| 1941 | |
| 1942 /* | |
| 1943 * Format one block of data for public/private key encryption using | |
| 1944 * the rules defined in PKCS #1. SSL2 does this itself to handle the | |
| 1945 * rollback detection. | |
| 1946 */ | |
| 1947 #define RSA_BLOCK_MIN_PAD_LEN 8 | |
| 1948 #define RSA_BLOCK_FIRST_OCTET 0x00 | |
| 1949 #define RSA_BLOCK_AFTER_PAD_OCTET 0x00 | |
| 1950 #define RSA_BLOCK_PUBLIC_OCTET 0x02 | |
| 1951 unsigned char * | |
| 1952 ssl_FormatSSL2Block(unsigned modulusLen, SECItem *data) | |
| 1953 { | |
| 1954 unsigned char *block; | |
| 1955 unsigned char *bp; | |
| 1956 int padLen; | |
| 1957 SECStatus rv; | |
| 1958 int i; | |
| 1959 | |
| 1960 if (modulusLen < data->len + (3 + RSA_BLOCK_MIN_PAD_LEN)) { | |
| 1961 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 1962 return NULL; | |
| 1963 } | |
| 1964 block = (unsigned char *) PORT_Alloc(modulusLen); | |
| 1965 if (block == NULL) | |
| 1966 return NULL; | |
| 1967 | |
| 1968 bp = block; | |
| 1969 | |
| 1970 /* | |
| 1971 * All RSA blocks start with two octets: | |
| 1972 * 0x00 || BlockType | |
| 1973 */ | |
| 1974 *bp++ = RSA_BLOCK_FIRST_OCTET; | |
| 1975 *bp++ = RSA_BLOCK_PUBLIC_OCTET; | |
| 1976 | |
| 1977 /* | |
| 1978 * 0x00 || BT || Pad || 0x00 || ActualData | |
| 1979 * 1 1 padLen 1 data->len | |
| 1980 * Pad is all non-zero random bytes. | |
| 1981 */ | |
| 1982 padLen = modulusLen - data->len - 3; | |
| 1983 PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN); | |
| 1984 rv = PK11_GenerateRandom(bp, padLen); | |
| 1985 if (rv == SECFailure) goto loser; | |
| 1986 /* replace all the 'zero' bytes */ | |
| 1987 for (i = 0; i < padLen; i++) { | |
| 1988 while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET) { | |
| 1989 rv = PK11_GenerateRandom(bp+i, 1); | |
| 1990 if (rv == SECFailure) goto loser; | |
| 1991 } | |
| 1992 } | |
| 1993 bp += padLen; | |
| 1994 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; | |
| 1995 PORT_Memcpy (bp, data->data, data->len); | |
| 1996 | |
| 1997 return block; | |
| 1998 loser: | |
| 1999 if (block) PORT_Free(block); | |
| 2000 return NULL; | |
| 2001 } | |
| 2002 | |
| 2003 /* | |
| 2004 ** Given the server's public key and cipher specs, generate a session key | |
| 2005 ** that is ready to use for encrypting/decrypting the byte stream. At | |
| 2006 ** the same time, generate the SSL_MT_CLIENT_MASTER_KEY message and | |
| 2007 ** send it to the server. | |
| 2008 ** | |
| 2009 ** Called from ssl2_HandleServerHelloMessage() | |
| 2010 */ | |
| 2011 static SECStatus | |
| 2012 ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen) | |
| 2013 { | |
| 2014 sslSessionID * sid; | |
| 2015 PRUint8 * ca; /* points to iv data, or NULL if none. */ | |
| 2016 PRUint8 * ekbuf = 0; | |
| 2017 CERTCertificate * cert = 0; | |
| 2018 SECKEYPublicKey * serverKey = 0; | |
| 2019 unsigned modulusLen = 0; | |
| 2020 SECStatus rv; | |
| 2021 int cipher; | |
| 2022 int keyLen; /* cipher symkey size in bytes. */ | |
| 2023 int ckLen; /* publicly reveal this many bytes of key. */ | |
| 2024 int caLen; /* length of IV data at *ca. */ | |
| 2025 int nc; | |
| 2026 | |
| 2027 unsigned char *eblock; /* holds unencrypted PKCS#1 formatted key. */ | |
| 2028 SECItem rek; /* holds portion of symkey to be encrypted. */ | |
| 2029 | |
| 2030 PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES]; | |
| 2031 PRUint8 iv [8]; | |
| 2032 | |
| 2033 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2034 | |
| 2035 eblock = NULL; | |
| 2036 | |
| 2037 sid = ss->sec.ci.sid; | |
| 2038 PORT_Assert(sid != 0); | |
| 2039 | |
| 2040 cert = ss->sec.peerCert; | |
| 2041 | |
| 2042 serverKey = CERT_ExtractPublicKey(cert); | |
| 2043 if (!serverKey) { | |
| 2044 SSL_DBG(("%d: SSL[%d]: extract public key failed: error=%d", | |
| 2045 SSL_GETPID(), ss->fd, PORT_GetError())); | |
| 2046 PORT_SetError(SSL_ERROR_BAD_CERTIFICATE); | |
| 2047 rv = SECFailure; | |
| 2048 goto loser2; | |
| 2049 } | |
| 2050 | |
| 2051 ss->sec.authAlgorithm = ssl_sign_rsa; | |
| 2052 ss->sec.keaType = ssl_kea_rsa; | |
| 2053 ss->sec.keaKeyBits = \ | |
| 2054 ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey); | |
| 2055 | |
| 2056 /* Choose a compatible cipher with the server */ | |
| 2057 nc = csLen / 3; | |
| 2058 cipher = ssl2_ChooseSessionCypher(ss, nc, cs, &keyLen); | |
| 2059 if (cipher < 0) { | |
| 2060 /* ssl2_ChooseSessionCypher has set error code. */ | |
| 2061 ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS); | |
| 2062 goto loser; | |
| 2063 } | |
| 2064 | |
| 2065 /* Generate the random keys */ | |
| 2066 PK11_GenerateRandom(keyData, sizeof(keyData)); | |
| 2067 | |
| 2068 /* | |
| 2069 ** Next, carve up the keys into clear and encrypted portions. The | |
| 2070 ** clear data is taken from the start of keyData and the encrypted | |
| 2071 ** portion from the remainder. Note that each of these portions is | |
| 2072 ** carved in half, one half for the read-key and one for the | |
| 2073 ** write-key. | |
| 2074 */ | |
| 2075 ca = 0; | |
| 2076 | |
| 2077 /* We know that cipher is a legit value here, because | |
| 2078 * ssl2_ChooseSessionCypher doesn't return bogus values. | |
| 2079 */ | |
| 2080 ckLen = ssl_Specs[cipher].pubLen; /* cleartext key length. */ | |
| 2081 caLen = ssl_Specs[cipher].ivLen; /* IV length. */ | |
| 2082 if (caLen) { | |
| 2083 PORT_Assert(sizeof iv >= caLen); | |
| 2084 PK11_GenerateRandom(iv, caLen); | |
| 2085 ca = iv; | |
| 2086 } | |
| 2087 | |
| 2088 /* Fill in session-id */ | |
| 2089 rv = ssl2_FillInSID(sid, cipher, keyData, keyLen, | |
| 2090 ca, caLen, keyLen << 3, (keyLen - ckLen) << 3, | |
| 2091 ss->sec.authAlgorithm, ss->sec.authKeyBits, | |
| 2092 ss->sec.keaType, ss->sec.keaKeyBits); | |
| 2093 if (rv != SECSuccess) { | |
| 2094 goto loser; | |
| 2095 } | |
| 2096 | |
| 2097 SSL_TRC(1, ("%d: SSL[%d]: client, using %s cipher, clear=%d total=%d", | |
| 2098 SSL_GETPID(), ss->fd, ssl_cipherName[cipher], | |
| 2099 ckLen<<3, keyLen<<3)); | |
| 2100 | |
| 2101 /* Now setup read and write ciphers */ | |
| 2102 rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE); | |
| 2103 if (rv != SECSuccess) { | |
| 2104 goto loser; | |
| 2105 } | |
| 2106 | |
| 2107 /* | |
| 2108 ** Fill in the encryption buffer with some random bytes. Then | |
| 2109 ** copy in the portion of the session key we are encrypting. | |
| 2110 */ | |
| 2111 modulusLen = SECKEY_PublicKeyStrength(serverKey); | |
| 2112 rek.data = keyData + ckLen; | |
| 2113 rek.len = keyLen - ckLen; | |
| 2114 eblock = ssl_FormatSSL2Block(modulusLen, &rek); | |
| 2115 if (eblock == NULL) | |
| 2116 goto loser; | |
| 2117 | |
| 2118 /* Set up the padding for version 2 rollback detection. */ | |
| 2119 /* XXX We should really use defines here */ | |
| 2120 if (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { | |
| 2121 PORT_Assert((modulusLen - rek.len) > 12); | |
| 2122 PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8); | |
| 2123 } | |
| 2124 ekbuf = (PRUint8*) PORT_Alloc(modulusLen); | |
| 2125 if (!ekbuf) | |
| 2126 goto loser; | |
| 2127 PRINT_BUF(10, (ss, "master key encryption block:", | |
| 2128 eblock, modulusLen)); | |
| 2129 | |
| 2130 /* Encrypt ekitem */ | |
| 2131 rv = PK11_PubEncryptRaw(serverKey, ekbuf, eblock, modulusLen, | |
| 2132 ss->pkcs11PinArg); | |
| 2133 if (rv) | |
| 2134 goto loser; | |
| 2135 | |
| 2136 /* Now we have everything ready to send */ | |
| 2137 rv = ssl2_SendSessionKeyMessage(ss, cipher, keyLen << 3, ca, caLen, | |
| 2138 keyData, ckLen, ekbuf, modulusLen); | |
| 2139 if (rv != SECSuccess) { | |
| 2140 goto loser; | |
| 2141 } | |
| 2142 rv = SECSuccess; | |
| 2143 goto done; | |
| 2144 | |
| 2145 loser: | |
| 2146 rv = SECFailure; | |
| 2147 | |
| 2148 loser2: | |
| 2149 done: | |
| 2150 PORT_Memset(keyData, 0, sizeof(keyData)); | |
| 2151 PORT_ZFree(ekbuf, modulusLen); | |
| 2152 PORT_ZFree(eblock, modulusLen); | |
| 2153 SECKEY_DestroyPublicKey(serverKey); | |
| 2154 return rv; | |
| 2155 } | |
| 2156 | |
| 2157 /************************************************************************/ | |
| 2158 | |
| 2159 /* | |
| 2160 * Called from ssl2_HandleMessage in response to SSL_MT_SERVER_FINISHED message. | |
| 2161 * Caller holds recvBufLock and handshakeLock | |
| 2162 */ | |
| 2163 static void | |
| 2164 ssl2_ClientRegSessionID(sslSocket *ss, PRUint8 *s) | |
| 2165 { | |
| 2166 sslSessionID *sid = ss->sec.ci.sid; | |
| 2167 | |
| 2168 /* Record entry in nonce cache */ | |
| 2169 if (sid->peerCert == NULL) { | |
| 2170 PORT_Memcpy(sid->u.ssl2.sessionID, s, sizeof(sid->u.ssl2.sessionID)); | |
| 2171 sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); | |
| 2172 | |
| 2173 } | |
| 2174 if (!ss->opt.noCache && sid->cached == never_cached) | |
| 2175 (*ss->sec.cache)(sid); | |
| 2176 } | |
| 2177 | |
| 2178 /* Called from ssl2_HandleMessage() */ | |
| 2179 static SECStatus | |
| 2180 ssl2_TriggerNextMessage(sslSocket *ss) | |
| 2181 { | |
| 2182 SECStatus rv; | |
| 2183 | |
| 2184 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2185 | |
| 2186 if ((ss->sec.ci.requiredElements & CIS_HAVE_CERTIFICATE) && | |
| 2187 !(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) { | |
| 2188 ss->sec.ci.sentElements |= CIS_HAVE_CERTIFICATE; | |
| 2189 rv = ssl2_SendCertificateRequestMessage(ss); | |
| 2190 return rv; | |
| 2191 } | |
| 2192 return SECSuccess; | |
| 2193 } | |
| 2194 | |
| 2195 /* See if it's time to send our finished message, or if the handshakes are | |
| 2196 ** complete. Send finished message if appropriate. | |
| 2197 ** Returns SECSuccess unless anything goes wrong. | |
| 2198 ** | |
| 2199 ** Called from ssl2_HandleMessage, | |
| 2200 ** ssl2_HandleVerifyMessage | |
| 2201 ** ssl2_HandleServerHelloMessage | |
| 2202 ** ssl2_HandleClientSessionKeyMessage | |
| 2203 */ | |
| 2204 static SECStatus | |
| 2205 ssl2_TryToFinish(sslSocket *ss) | |
| 2206 { | |
| 2207 SECStatus rv; | |
| 2208 char e, ef; | |
| 2209 | |
| 2210 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2211 | |
| 2212 e = ss->sec.ci.elements; | |
| 2213 ef = e | CIS_HAVE_FINISHED; | |
| 2214 if ((ef & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) { | |
| 2215 if (ss->sec.isServer) { | |
| 2216 /* Send server finished message if we already didn't */ | |
| 2217 rv = ssl2_SendServerFinishedMessage(ss); | |
| 2218 } else { | |
| 2219 /* Send client finished message if we already didn't */ | |
| 2220 rv = ssl2_SendClientFinishedMessage(ss); | |
| 2221 } | |
| 2222 if (rv != SECSuccess) { | |
| 2223 return rv; | |
| 2224 } | |
| 2225 if ((e & ss->sec.ci.requiredElements) == ss->sec.ci.requiredElements) { | |
| 2226 /* Totally finished */ | |
| 2227 ss->handshake = 0; | |
| 2228 return SECSuccess; | |
| 2229 } | |
| 2230 } | |
| 2231 return SECSuccess; | |
| 2232 } | |
| 2233 | |
| 2234 /* | |
| 2235 ** Called from ssl2_HandleRequestCertificate | |
| 2236 */ | |
| 2237 static SECStatus | |
| 2238 ssl2_SignResponse(sslSocket *ss, | |
| 2239 SECKEYPrivateKey *key, | |
| 2240 SECItem *response) | |
| 2241 { | |
| 2242 SGNContext * sgn = NULL; | |
| 2243 PRUint8 * challenge; | |
| 2244 unsigned int len; | |
| 2245 SECStatus rv = SECFailure; | |
| 2246 | |
| 2247 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2248 | |
| 2249 challenge = ss->sec.ci.serverChallenge; | |
| 2250 len = ss->sec.ci.serverChallengeLen; | |
| 2251 | |
| 2252 /* Sign the expected data... */ | |
| 2253 sgn = SGN_NewContext(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,key); | |
| 2254 if (!sgn) | |
| 2255 goto done; | |
| 2256 rv = SGN_Begin(sgn); | |
| 2257 if (rv != SECSuccess) | |
| 2258 goto done; | |
| 2259 rv = SGN_Update(sgn, ss->sec.ci.readKey, ss->sec.ci.keySize); | |
| 2260 if (rv != SECSuccess) | |
| 2261 goto done; | |
| 2262 rv = SGN_Update(sgn, ss->sec.ci.writeKey, ss->sec.ci.keySize); | |
| 2263 if (rv != SECSuccess) | |
| 2264 goto done; | |
| 2265 rv = SGN_Update(sgn, challenge, len); | |
| 2266 if (rv != SECSuccess) | |
| 2267 goto done; | |
| 2268 rv = SGN_Update(sgn, ss->sec.peerCert->derCert.data, | |
| 2269 ss->sec.peerCert->derCert.len); | |
| 2270 if (rv != SECSuccess) | |
| 2271 goto done; | |
| 2272 rv = SGN_End(sgn, response); | |
| 2273 if (rv != SECSuccess) | |
| 2274 goto done; | |
| 2275 | |
| 2276 done: | |
| 2277 SGN_DestroyContext(sgn, PR_TRUE); | |
| 2278 return rv == SECSuccess ? SECSuccess : SECFailure; | |
| 2279 } | |
| 2280 | |
| 2281 /* | |
| 2282 ** Try to handle a request-certificate message. Get client's certificate | |
| 2283 ** and private key and sign a message for the server to see. | |
| 2284 ** Caller must hold handshakeLock | |
| 2285 ** | |
| 2286 ** Called from ssl2_HandleMessage(). | |
| 2287 */ | |
| 2288 static int | |
| 2289 ssl2_HandleRequestCertificate(sslSocket *ss) | |
| 2290 { | |
| 2291 CERTCertificate * cert = NULL; /* app-selected client cert. */ | |
| 2292 SECKEYPrivateKey *key = NULL; /* priv key for cert. */ | |
| 2293 SECStatus rv; | |
| 2294 SECItem response; | |
| 2295 int ret = 0; | |
| 2296 PRUint8 authType; | |
| 2297 | |
| 2298 | |
| 2299 /* | |
| 2300 * These things all need to be initialized before we can "goto loser". | |
| 2301 */ | |
| 2302 response.data = NULL; | |
| 2303 | |
| 2304 /* get challenge info from connectionInfo */ | |
| 2305 authType = ss->sec.ci.authType; | |
| 2306 | |
| 2307 if (authType != SSL_AT_MD5_WITH_RSA_ENCRYPTION) { | |
| 2308 SSL_TRC(7, ("%d: SSL[%d]: unsupported auth type 0x%x", SSL_GETPID(), | |
| 2309 ss->fd, authType)); | |
| 2310 goto no_cert_error; | |
| 2311 } | |
| 2312 | |
| 2313 /* Get certificate and private-key from client */ | |
| 2314 if (!ss->getClientAuthData) { | |
| 2315 SSL_TRC(7, ("%d: SSL[%d]: client doesn't support client-auth", | |
| 2316 SSL_GETPID(), ss->fd)); | |
| 2317 goto no_cert_error; | |
| 2318 } | |
| 2319 ret = (*ss->getClientAuthData)(ss->getClientAuthDataArg, ss->fd, | |
| 2320 NULL, &cert, &key); | |
| 2321 if ( ret == SECWouldBlock ) { | |
| 2322 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 2323 ret = -1; | |
| 2324 goto loser; | |
| 2325 } | |
| 2326 | |
| 2327 if (ret) { | |
| 2328 goto no_cert_error; | |
| 2329 } | |
| 2330 | |
| 2331 /* check what the callback function returned */ | |
| 2332 if ((!cert) || (!key)) { | |
| 2333 /* we are missing either the key or cert */ | |
| 2334 if (cert) { | |
| 2335 /* got a cert, but no key - free it */ | |
| 2336 CERT_DestroyCertificate(cert); | |
| 2337 cert = NULL; | |
| 2338 } | |
| 2339 if (key) { | |
| 2340 /* got a key, but no cert - free it */ | |
| 2341 SECKEY_DestroyPrivateKey(key); | |
| 2342 key = NULL; | |
| 2343 } | |
| 2344 goto no_cert_error; | |
| 2345 } | |
| 2346 | |
| 2347 rv = ssl2_SignResponse(ss, key, &response); | |
| 2348 if ( rv != SECSuccess ) { | |
| 2349 ret = -1; | |
| 2350 goto loser; | |
| 2351 } | |
| 2352 | |
| 2353 /* Send response message */ | |
| 2354 ret = ssl2_SendCertificateResponseMessage(ss, &cert->derCert, &response); | |
| 2355 | |
| 2356 /* Now, remember the cert we sent. But first, forget any previous one. */ | |
| 2357 if (ss->sec.localCert) { | |
| 2358 CERT_DestroyCertificate(ss->sec.localCert); | |
| 2359 } | |
| 2360 ss->sec.localCert = CERT_DupCertificate(cert); | |
| 2361 PORT_Assert(!ss->sec.ci.sid->localCert); | |
| 2362 if (ss->sec.ci.sid->localCert) { | |
| 2363 CERT_DestroyCertificate(ss->sec.ci.sid->localCert); | |
| 2364 } | |
| 2365 ss->sec.ci.sid->localCert = cert; | |
| 2366 cert = NULL; | |
| 2367 | |
| 2368 goto done; | |
| 2369 | |
| 2370 no_cert_error: | |
| 2371 SSL_TRC(7, ("%d: SSL[%d]: no certificate (ret=%d)", SSL_GETPID(), | |
| 2372 ss->fd, ret)); | |
| 2373 ret = ssl2_SendErrorMessage(ss, SSL_PE_NO_CERTIFICATE); | |
| 2374 | |
| 2375 loser: | |
| 2376 done: | |
| 2377 if ( cert ) { | |
| 2378 CERT_DestroyCertificate(cert); | |
| 2379 } | |
| 2380 if ( key ) { | |
| 2381 SECKEY_DestroyPrivateKey(key); | |
| 2382 } | |
| 2383 if ( response.data ) { | |
| 2384 PORT_Free(response.data); | |
| 2385 } | |
| 2386 | |
| 2387 return ret; | |
| 2388 } | |
| 2389 | |
| 2390 /* | |
| 2391 ** Called from ssl2_HandleMessage for SSL_MT_CLIENT_CERTIFICATE message. | |
| 2392 ** Caller must hold HandshakeLock and RecvBufLock, since cd and response | |
| 2393 ** are contained in the gathered input data. | |
| 2394 */ | |
| 2395 static SECStatus | |
| 2396 ssl2_HandleClientCertificate(sslSocket * ss, | |
| 2397 PRUint8 certType, /* XXX unused */ | |
| 2398 PRUint8 * cd, | |
| 2399 unsigned int cdLen, | |
| 2400 PRUint8 * response, | |
| 2401 unsigned int responseLen) | |
| 2402 { | |
| 2403 CERTCertificate *cert = NULL; | |
| 2404 SECKEYPublicKey *pubKey = NULL; | |
| 2405 VFYContext * vfy = NULL; | |
| 2406 SECItem * derCert; | |
| 2407 SECStatus rv = SECFailure; | |
| 2408 SECItem certItem; | |
| 2409 SECItem rep; | |
| 2410 | |
| 2411 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2412 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 2413 | |
| 2414 /* Extract the certificate */ | |
| 2415 certItem.data = cd; | |
| 2416 certItem.len = cdLen; | |
| 2417 | |
| 2418 cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, | |
| 2419 PR_FALSE, PR_TRUE); | |
| 2420 if (cert == NULL) { | |
| 2421 goto loser; | |
| 2422 } | |
| 2423 | |
| 2424 /* save the certificate, since the auth routine will need it */ | |
| 2425 ss->sec.peerCert = cert; | |
| 2426 | |
| 2427 /* Extract the public key */ | |
| 2428 pubKey = CERT_ExtractPublicKey(cert); | |
| 2429 if (!pubKey) | |
| 2430 goto loser; | |
| 2431 | |
| 2432 /* Verify the response data... */ | |
| 2433 rep.data = response; | |
| 2434 rep.len = responseLen; | |
| 2435 /* SSL 2.0 only supports RSA certs, so we don't have to worry about | |
| 2436 * DSA here. */ | |
| 2437 vfy = VFY_CreateContext(pubKey, &rep, SEC_OID_PKCS1_RSA_ENCRYPTION, | |
| 2438 ss->pkcs11PinArg); | |
| 2439 if (!vfy) | |
| 2440 goto loser; | |
| 2441 rv = VFY_Begin(vfy); | |
| 2442 if (rv) | |
| 2443 goto loser; | |
| 2444 | |
| 2445 rv = VFY_Update(vfy, ss->sec.ci.readKey, ss->sec.ci.keySize); | |
| 2446 if (rv) | |
| 2447 goto loser; | |
| 2448 rv = VFY_Update(vfy, ss->sec.ci.writeKey, ss->sec.ci.keySize); | |
| 2449 if (rv) | |
| 2450 goto loser; | |
| 2451 rv = VFY_Update(vfy, ss->sec.ci.serverChallenge, SSL_CHALLENGE_BYTES); | |
| 2452 if (rv) | |
| 2453 goto loser; | |
| 2454 | |
| 2455 derCert = &ss->serverCerts[kt_rsa].serverCert->derCert; | |
| 2456 rv = VFY_Update(vfy, derCert->data, derCert->len); | |
| 2457 if (rv) | |
| 2458 goto loser; | |
| 2459 rv = VFY_End(vfy); | |
| 2460 if (rv) | |
| 2461 goto loser; | |
| 2462 | |
| 2463 /* Now ask the server application if it likes the certificate... */ | |
| 2464 rv = (SECStatus) (*ss->authCertificate)(ss->authCertificateArg, | |
| 2465 ss->fd, PR_TRUE, PR_TRUE); | |
| 2466 /* Hey, it liked it. */ | |
| 2467 if (SECSuccess == rv) | |
| 2468 goto done; | |
| 2469 | |
| 2470 loser: | |
| 2471 ss->sec.peerCert = NULL; | |
| 2472 CERT_DestroyCertificate(cert); | |
| 2473 | |
| 2474 done: | |
| 2475 VFY_DestroyContext(vfy, PR_TRUE); | |
| 2476 SECKEY_DestroyPublicKey(pubKey); | |
| 2477 return rv; | |
| 2478 } | |
| 2479 | |
| 2480 /* | |
| 2481 ** Handle remaining messages between client/server. Process finished | |
| 2482 ** messages from either side and any authentication requests. | |
| 2483 ** This should only be called for SSLv2 handshake messages, | |
| 2484 ** not for application data records. | |
| 2485 ** Caller must hold handshake lock. | |
| 2486 ** | |
| 2487 ** Called from ssl_Do1stHandshake(). | |
| 2488 ** | |
| 2489 */ | |
| 2490 static SECStatus | |
| 2491 ssl2_HandleMessage(sslSocket *ss) | |
| 2492 { | |
| 2493 PRUint8 * data; | |
| 2494 PRUint8 * cid; | |
| 2495 unsigned len, certType, certLen, responseLen; | |
| 2496 int rv; | |
| 2497 int rv2; | |
| 2498 | |
| 2499 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2500 | |
| 2501 ssl_GetRecvBufLock(ss); | |
| 2502 | |
| 2503 data = ss->gs.buf.buf + ss->gs.recordOffset; | |
| 2504 | |
| 2505 if (ss->gs.recordLen < 1) { | |
| 2506 goto bad_peer; | |
| 2507 } | |
| 2508 SSL_TRC(3, ("%d: SSL[%d]: received %d message", | |
| 2509 SSL_GETPID(), ss->fd, data[0])); | |
| 2510 DUMP_MSG(29, (ss, data, ss->gs.recordLen)); | |
| 2511 | |
| 2512 switch (data[0]) { | |
| 2513 case SSL_MT_CLIENT_FINISHED: | |
| 2514 if (ss->sec.ci.elements & CIS_HAVE_FINISHED) { | |
| 2515 SSL_DBG(("%d: SSL[%d]: dup client-finished message", | |
| 2516 SSL_GETPID(), ss->fd)); | |
| 2517 goto bad_peer; | |
| 2518 } | |
| 2519 | |
| 2520 /* See if nonce matches */ | |
| 2521 len = ss->gs.recordLen - 1; | |
| 2522 cid = data + 1; | |
| 2523 if ((len != sizeof(ss->sec.ci.connectionID)) || | |
| 2524 (PORT_Memcmp(ss->sec.ci.connectionID, cid, len) != 0)) { | |
| 2525 SSL_DBG(("%d: SSL[%d]: bad connection-id", SSL_GETPID(), ss->fd)); | |
| 2526 PRINT_BUF(5, (ss, "sent connection-id", | |
| 2527 ss->sec.ci.connectionID, | |
| 2528 sizeof(ss->sec.ci.connectionID))); | |
| 2529 PRINT_BUF(5, (ss, "rcvd connection-id", cid, len)); | |
| 2530 goto bad_peer; | |
| 2531 } | |
| 2532 | |
| 2533 SSL_TRC(5, ("%d: SSL[%d]: got client finished, waiting for 0x%d", | |
| 2534 SSL_GETPID(), ss->fd, | |
| 2535 ss->sec.ci.requiredElements ^ ss->sec.ci.elements)); | |
| 2536 ss->sec.ci.elements |= CIS_HAVE_FINISHED; | |
| 2537 break; | |
| 2538 | |
| 2539 case SSL_MT_SERVER_FINISHED: | |
| 2540 if (ss->sec.ci.elements & CIS_HAVE_FINISHED) { | |
| 2541 SSL_DBG(("%d: SSL[%d]: dup server-finished message", | |
| 2542 SSL_GETPID(), ss->fd)); | |
| 2543 goto bad_peer; | |
| 2544 } | |
| 2545 | |
| 2546 if (ss->gs.recordLen - 1 != SSL2_SESSIONID_BYTES) { | |
| 2547 SSL_DBG(("%d: SSL[%d]: bad server-finished message, len=%d", | |
| 2548 SSL_GETPID(), ss->fd, ss->gs.recordLen)); | |
| 2549 goto bad_peer; | |
| 2550 } | |
| 2551 ssl2_ClientRegSessionID(ss, data+1); | |
| 2552 SSL_TRC(5, ("%d: SSL[%d]: got server finished, waiting for 0x%d", | |
| 2553 SSL_GETPID(), ss->fd, | |
| 2554 ss->sec.ci.requiredElements ^ ss->sec.ci.elements)); | |
| 2555 ss->sec.ci.elements |= CIS_HAVE_FINISHED; | |
| 2556 break; | |
| 2557 | |
| 2558 case SSL_MT_REQUEST_CERTIFICATE: | |
| 2559 len = ss->gs.recordLen - 2; | |
| 2560 if ((len < SSL_MIN_CHALLENGE_BYTES) || | |
| 2561 (len > SSL_MAX_CHALLENGE_BYTES)) { | |
| 2562 /* Bad challenge */ | |
| 2563 SSL_DBG(("%d: SSL[%d]: bad cert request message: code len=%d", | |
| 2564 SSL_GETPID(), ss->fd, len)); | |
| 2565 goto bad_peer; | |
| 2566 } | |
| 2567 | |
| 2568 /* save auth request info */ | |
| 2569 ss->sec.ci.authType = data[1]; | |
| 2570 ss->sec.ci.serverChallengeLen = len; | |
| 2571 PORT_Memcpy(ss->sec.ci.serverChallenge, data + 2, len); | |
| 2572 | |
| 2573 rv = ssl2_HandleRequestCertificate(ss); | |
| 2574 if (rv == SECWouldBlock) { | |
| 2575 SSL_TRC(3, ("%d: SSL[%d]: async cert request", | |
| 2576 SSL_GETPID(), ss->fd)); | |
| 2577 /* someone is handling this asynchronously */ | |
| 2578 ssl_ReleaseRecvBufLock(ss); | |
| 2579 return SECWouldBlock; | |
| 2580 } | |
| 2581 if (rv) { | |
| 2582 SET_ERROR_CODE | |
| 2583 goto loser; | |
| 2584 } | |
| 2585 break; | |
| 2586 | |
| 2587 case SSL_MT_CLIENT_CERTIFICATE: | |
| 2588 if (!ss->authCertificate) { | |
| 2589 /* Server asked for authentication and can't handle it */ | |
| 2590 PORT_SetError(SSL_ERROR_BAD_SERVER); | |
| 2591 goto loser; | |
| 2592 } | |
| 2593 if (ss->gs.recordLen < SSL_HL_CLIENT_CERTIFICATE_HBYTES) { | |
| 2594 SET_ERROR_CODE | |
| 2595 goto loser; | |
| 2596 } | |
| 2597 certType = data[1]; | |
| 2598 certLen = (data[2] << 8) | data[3]; | |
| 2599 responseLen = (data[4] << 8) | data[5]; | |
| 2600 if (certType != SSL_CT_X509_CERTIFICATE) { | |
| 2601 PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); | |
| 2602 goto loser; | |
| 2603 } | |
| 2604 if (certLen + responseLen + SSL_HL_CLIENT_CERTIFICATE_HBYTES | |
| 2605 > ss->gs.recordLen) { | |
| 2606 /* prevent overflow crash. */ | |
| 2607 rv = SECFailure; | |
| 2608 } else | |
| 2609 rv = ssl2_HandleClientCertificate(ss, data[1], | |
| 2610 data + SSL_HL_CLIENT_CERTIFICATE_HBYTES, | |
| 2611 certLen, | |
| 2612 data + SSL_HL_CLIENT_CERTIFICATE_HBYTES + certLen, | |
| 2613 responseLen); | |
| 2614 if (rv) { | |
| 2615 rv2 = ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE); | |
| 2616 SET_ERROR_CODE | |
| 2617 goto loser; | |
| 2618 } | |
| 2619 ss->sec.ci.elements |= CIS_HAVE_CERTIFICATE; | |
| 2620 break; | |
| 2621 | |
| 2622 case SSL_MT_ERROR: | |
| 2623 rv = (data[1] << 8) | data[2]; | |
| 2624 SSL_TRC(2, ("%d: SSL[%d]: got error message, error=0x%x", | |
| 2625 SSL_GETPID(), ss->fd, rv)); | |
| 2626 | |
| 2627 /* Convert protocol error number into API error number */ | |
| 2628 switch (rv) { | |
| 2629 case SSL_PE_NO_CYPHERS: | |
| 2630 rv = SSL_ERROR_NO_CYPHER_OVERLAP; | |
| 2631 break; | |
| 2632 case SSL_PE_NO_CERTIFICATE: | |
| 2633 rv = SSL_ERROR_NO_CERTIFICATE; | |
| 2634 break; | |
| 2635 case SSL_PE_BAD_CERTIFICATE: | |
| 2636 rv = SSL_ERROR_BAD_CERTIFICATE; | |
| 2637 break; | |
| 2638 case SSL_PE_UNSUPPORTED_CERTIFICATE_TYPE: | |
| 2639 rv = SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE; | |
| 2640 break; | |
| 2641 default: | |
| 2642 goto bad_peer; | |
| 2643 } | |
| 2644 /* XXX make certificate-request optionally fail... */ | |
| 2645 PORT_SetError(rv); | |
| 2646 goto loser; | |
| 2647 | |
| 2648 default: | |
| 2649 SSL_DBG(("%d: SSL[%d]: unknown message %d", | |
| 2650 SSL_GETPID(), ss->fd, data[0])); | |
| 2651 goto loser; | |
| 2652 } | |
| 2653 | |
| 2654 SSL_TRC(3, ("%d: SSL[%d]: handled %d message, required=0x%x got=0x%x", | |
| 2655 SSL_GETPID(), ss->fd, data[0], | |
| 2656 ss->sec.ci.requiredElements, ss->sec.ci.elements)); | |
| 2657 | |
| 2658 rv = ssl2_TryToFinish(ss); | |
| 2659 if (rv != SECSuccess) | |
| 2660 goto loser; | |
| 2661 | |
| 2662 ss->gs.recordLen = 0; | |
| 2663 ssl_ReleaseRecvBufLock(ss); | |
| 2664 | |
| 2665 if (ss->handshake == 0) { | |
| 2666 return SECSuccess; | |
| 2667 } | |
| 2668 | |
| 2669 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 2670 ss->nextHandshake = ssl2_HandleMessage; | |
| 2671 return ssl2_TriggerNextMessage(ss); | |
| 2672 | |
| 2673 bad_peer: | |
| 2674 PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT : SSL_ERROR_BAD_SERVER
); | |
| 2675 /* FALL THROUGH */ | |
| 2676 | |
| 2677 loser: | |
| 2678 ssl_ReleaseRecvBufLock(ss); | |
| 2679 return SECFailure; | |
| 2680 } | |
| 2681 | |
| 2682 /************************************************************************/ | |
| 2683 | |
| 2684 /* Called from ssl_Do1stHandshake, after ssl2_HandleServerHelloMessage. | |
| 2685 */ | |
| 2686 static SECStatus | |
| 2687 ssl2_HandleVerifyMessage(sslSocket *ss) | |
| 2688 { | |
| 2689 PRUint8 * data; | |
| 2690 SECStatus rv; | |
| 2691 | |
| 2692 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2693 ssl_GetRecvBufLock(ss); | |
| 2694 | |
| 2695 data = ss->gs.buf.buf + ss->gs.recordOffset; | |
| 2696 DUMP_MSG(29, (ss, data, ss->gs.recordLen)); | |
| 2697 if ((ss->gs.recordLen != 1 + SSL_CHALLENGE_BYTES) || | |
| 2698 (data[0] != SSL_MT_SERVER_VERIFY) || | |
| 2699 NSS_SecureMemcmp(data+1, ss->sec.ci.clientChallenge, | |
| 2700 SSL_CHALLENGE_BYTES)) { | |
| 2701 /* Bad server */ | |
| 2702 PORT_SetError(SSL_ERROR_BAD_SERVER); | |
| 2703 goto loser; | |
| 2704 } | |
| 2705 ss->sec.ci.elements |= CIS_HAVE_VERIFY; | |
| 2706 | |
| 2707 SSL_TRC(5, ("%d: SSL[%d]: got server-verify, required=0x%d got=0x%x", | |
| 2708 SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements, | |
| 2709 ss->sec.ci.elements)); | |
| 2710 | |
| 2711 rv = ssl2_TryToFinish(ss); | |
| 2712 if (rv) | |
| 2713 goto loser; | |
| 2714 | |
| 2715 ss->gs.recordLen = 0; | |
| 2716 ssl_ReleaseRecvBufLock(ss); | |
| 2717 | |
| 2718 if (ss->handshake == 0) { | |
| 2719 return SECSuccess; | |
| 2720 } | |
| 2721 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 2722 ss->nextHandshake = ssl2_HandleMessage; | |
| 2723 return SECSuccess; | |
| 2724 | |
| 2725 | |
| 2726 loser: | |
| 2727 ssl_ReleaseRecvBufLock(ss); | |
| 2728 return SECFailure; | |
| 2729 } | |
| 2730 | |
| 2731 /* Not static because ssl2_GatherData() tests ss->nextHandshake for this value. | |
| 2732 * ICK! | |
| 2733 * Called from ssl_Do1stHandshake after ssl2_BeginClientHandshake() | |
| 2734 */ | |
| 2735 SECStatus | |
| 2736 ssl2_HandleServerHelloMessage(sslSocket *ss) | |
| 2737 { | |
| 2738 sslSessionID * sid; | |
| 2739 PRUint8 * cert; | |
| 2740 PRUint8 * cs; | |
| 2741 PRUint8 * data; | |
| 2742 SECStatus rv; | |
| 2743 int needed, sidHit, certLen, csLen, cidLen, certType, err; | |
| 2744 | |
| 2745 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2746 | |
| 2747 if (!ss->opt.enableSSL2) { | |
| 2748 PORT_SetError(SSL_ERROR_SSL2_DISABLED); | |
| 2749 return SECFailure; | |
| 2750 } | |
| 2751 | |
| 2752 ssl_GetRecvBufLock(ss); | |
| 2753 | |
| 2754 PORT_Assert(ss->sec.ci.sid != 0); | |
| 2755 sid = ss->sec.ci.sid; | |
| 2756 | |
| 2757 data = ss->gs.buf.buf + ss->gs.recordOffset; | |
| 2758 DUMP_MSG(29, (ss, data, ss->gs.recordLen)); | |
| 2759 | |
| 2760 /* Make sure first message has some data and is the server hello message */ | |
| 2761 if ((ss->gs.recordLen < SSL_HL_SERVER_HELLO_HBYTES) | |
| 2762 || (data[0] != SSL_MT_SERVER_HELLO)) { | |
| 2763 if ((data[0] == SSL_MT_ERROR) && (ss->gs.recordLen == 3)) { | |
| 2764 err = (data[1] << 8) | data[2]; | |
| 2765 if (err == SSL_PE_NO_CYPHERS) { | |
| 2766 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 2767 goto loser; | |
| 2768 } | |
| 2769 } | |
| 2770 goto bad_server; | |
| 2771 } | |
| 2772 | |
| 2773 sidHit = data[1]; | |
| 2774 certType = data[2]; | |
| 2775 ss->version = (data[3] << 8) | data[4]; | |
| 2776 certLen = (data[5] << 8) | data[6]; | |
| 2777 csLen = (data[7] << 8) | data[8]; | |
| 2778 cidLen = (data[9] << 8) | data[10]; | |
| 2779 cert = data + SSL_HL_SERVER_HELLO_HBYTES; | |
| 2780 cs = cert + certLen; | |
| 2781 | |
| 2782 SSL_TRC(5, | |
| 2783 ("%d: SSL[%d]: server-hello, hit=%d vers=%x certLen=%d csLen=%d cidL
en=%d", | |
| 2784 SSL_GETPID(), ss->fd, sidHit, ss->version, certLen, | |
| 2785 csLen, cidLen)); | |
| 2786 if (ss->version != SSL_LIBRARY_VERSION_2) { | |
| 2787 if (ss->version < SSL_LIBRARY_VERSION_2) { | |
| 2788 SSL_TRC(3, ("%d: SSL[%d]: demoting self (%x) to server version (%x)", | |
| 2789 SSL_GETPID(), ss->fd, SSL_LIBRARY_VERSION_2, | |
| 2790 ss->version)); | |
| 2791 } else { | |
| 2792 SSL_TRC(1, ("%d: SSL[%d]: server version is %x (we are %x)", | |
| 2793 SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2)); | |
| 2794 /* server claims to be newer but does not follow protocol */ | |
| 2795 PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION); | |
| 2796 goto loser; | |
| 2797 } | |
| 2798 } | |
| 2799 | |
| 2800 if ((SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen + cidLen | |
| 2801 > ss->gs.recordLen) | |
| 2802 || (csLen % 3) != 0 | |
| 2803 /* || cidLen < SSL_CONNECTIONID_BYTES || cidLen > 32 */ | |
| 2804 ) { | |
| 2805 goto bad_server; | |
| 2806 } | |
| 2807 | |
| 2808 /* Save connection-id. | |
| 2809 ** This code only saves the first 16 byte of the connectionID. | |
| 2810 ** If the connectionID is shorter than 16 bytes, it is zero-padded. | |
| 2811 */ | |
| 2812 if (cidLen < sizeof ss->sec.ci.connectionID) | |
| 2813 memset(ss->sec.ci.connectionID, 0, sizeof ss->sec.ci.connectionID); | |
| 2814 cidLen = PR_MIN(cidLen, sizeof ss->sec.ci.connectionID); | |
| 2815 PORT_Memcpy(ss->sec.ci.connectionID, cs + csLen, cidLen); | |
| 2816 | |
| 2817 /* See if session-id hit */ | |
| 2818 needed = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED | CIS_HAVE_VERIFY; | |
| 2819 if (sidHit) { | |
| 2820 if (certLen || csLen) { | |
| 2821 /* Uh oh - bogus server */ | |
| 2822 SSL_DBG(("%d: SSL[%d]: client, huh? hit=%d certLen=%d csLen=%d", | |
| 2823 SSL_GETPID(), ss->fd, sidHit, certLen, csLen)); | |
| 2824 goto bad_server; | |
| 2825 } | |
| 2826 | |
| 2827 /* Total winner. */ | |
| 2828 SSL_TRC(1, ("%d: SSL[%d]: client, using nonce for peer=0x%08x " | |
| 2829 "port=0x%04x", | |
| 2830 SSL_GETPID(), ss->fd, ss->sec.ci.peer, ss->sec.ci.port)); | |
| 2831 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); | |
| 2832 ss->sec.authAlgorithm = sid->authAlgorithm; | |
| 2833 ss->sec.authKeyBits = sid->authKeyBits; | |
| 2834 ss->sec.keaType = sid->keaType; | |
| 2835 ss->sec.keaKeyBits = sid->keaKeyBits; | |
| 2836 rv = ssl2_CreateSessionCypher(ss, sid, PR_TRUE); | |
| 2837 if (rv != SECSuccess) { | |
| 2838 goto loser; | |
| 2839 } | |
| 2840 } else { | |
| 2841 if (certType != SSL_CT_X509_CERTIFICATE) { | |
| 2842 PORT_SetError(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); | |
| 2843 goto loser; | |
| 2844 } | |
| 2845 if (csLen == 0) { | |
| 2846 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 2847 SSL_DBG(("%d: SSL[%d]: no cipher overlap", | |
| 2848 SSL_GETPID(), ss->fd)); | |
| 2849 goto loser; | |
| 2850 } | |
| 2851 if (certLen == 0) { | |
| 2852 SSL_DBG(("%d: SSL[%d]: client, huh? certLen=%d csLen=%d", | |
| 2853 SSL_GETPID(), ss->fd, certLen, csLen)); | |
| 2854 goto bad_server; | |
| 2855 } | |
| 2856 | |
| 2857 if (sid->cached != never_cached) { | |
| 2858 /* Forget our session-id - server didn't like it */ | |
| 2859 SSL_TRC(7, ("%d: SSL[%d]: server forgot me, uncaching session-id", | |
| 2860 SSL_GETPID(), ss->fd)); | |
| 2861 if (ss->sec.uncache) | |
| 2862 (*ss->sec.uncache)(sid); | |
| 2863 ssl_FreeSID(sid); | |
| 2864 ss->sec.ci.sid = sid = PORT_ZNew(sslSessionID); | |
| 2865 if (!sid) { | |
| 2866 goto loser; | |
| 2867 } | |
| 2868 sid->references = 1; | |
| 2869 sid->addr = ss->sec.ci.peer; | |
| 2870 sid->port = ss->sec.ci.port; | |
| 2871 } | |
| 2872 | |
| 2873 /* decode the server's certificate */ | |
| 2874 rv = ssl2_ClientHandleServerCert(ss, cert, certLen); | |
| 2875 if (rv != SECSuccess) { | |
| 2876 if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) { | |
| 2877 (void) ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE); | |
| 2878 } | |
| 2879 goto loser; | |
| 2880 } | |
| 2881 | |
| 2882 /* Setup new session cipher */ | |
| 2883 rv = ssl2_ClientSetupSessionCypher(ss, cs, csLen); | |
| 2884 if (rv != SECSuccess) { | |
| 2885 if (PORT_GetError() == SSL_ERROR_BAD_CERTIFICATE) { | |
| 2886 (void) ssl2_SendErrorMessage(ss, SSL_PE_BAD_CERTIFICATE); | |
| 2887 } | |
| 2888 goto loser; | |
| 2889 } | |
| 2890 } | |
| 2891 | |
| 2892 /* Build up final list of required elements */ | |
| 2893 ss->sec.ci.elements = CIS_HAVE_MASTER_KEY; | |
| 2894 ss->sec.ci.requiredElements = needed; | |
| 2895 | |
| 2896 if (!sidHit) { | |
| 2897 /* verify the server's certificate. if sidHit, don't check signatures */ | |
| 2898 rv = (* ss->authCertificate)(ss->authCertificateArg, ss->fd, | |
| 2899 (PRBool)(!sidHit), PR_FALSE); | |
| 2900 if (rv) { | |
| 2901 if (ss->handleBadCert) { | |
| 2902 rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd); | |
| 2903 if ( rv ) { | |
| 2904 if ( rv == SECWouldBlock ) { | |
| 2905 SSL_DBG(("%d: SSL[%d]: SSL2 bad cert handler returned " | |
| 2906 "SECWouldBlock", SSL_GETPID(), ss->fd)); | |
| 2907 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 2908 rv = SECFailure; | |
| 2909 } else { | |
| 2910 /* cert is bad */ | |
| 2911 SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=
%d", | |
| 2912 SSL_GETPID(), ss->fd, PORT_GetError())); | |
| 2913 } | |
| 2914 goto loser; | |
| 2915 } | |
| 2916 /* cert is good */ | |
| 2917 } else { | |
| 2918 SSL_DBG(("%d: SSL[%d]: server certificate is no good: error=%d", | |
| 2919 SSL_GETPID(), ss->fd, PORT_GetError())); | |
| 2920 goto loser; | |
| 2921 } | |
| 2922 } | |
| 2923 } | |
| 2924 /* | |
| 2925 ** At this point we have a completed session key and our session | |
| 2926 ** cipher is setup and ready to go. Switch to encrypted write routine | |
| 2927 ** as all future message data is to be encrypted. | |
| 2928 */ | |
| 2929 ssl2_UseEncryptedSendFunc(ss); | |
| 2930 | |
| 2931 rv = ssl2_TryToFinish(ss); | |
| 2932 if (rv != SECSuccess) | |
| 2933 goto loser; | |
| 2934 | |
| 2935 ss->gs.recordLen = 0; | |
| 2936 | |
| 2937 ssl_ReleaseRecvBufLock(ss); | |
| 2938 | |
| 2939 if (ss->handshake == 0) { | |
| 2940 return SECSuccess; | |
| 2941 } | |
| 2942 | |
| 2943 SSL_TRC(5, ("%d: SSL[%d]: got server-hello, required=0x%d got=0x%x", | |
| 2944 SSL_GETPID(), ss->fd, ss->sec.ci.requiredElements, | |
| 2945 ss->sec.ci.elements)); | |
| 2946 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 2947 ss->nextHandshake = ssl2_HandleVerifyMessage; | |
| 2948 return SECSuccess; | |
| 2949 | |
| 2950 bad_server: | |
| 2951 PORT_SetError(SSL_ERROR_BAD_SERVER); | |
| 2952 /* FALL THROUGH */ | |
| 2953 | |
| 2954 loser: | |
| 2955 ssl_ReleaseRecvBufLock(ss); | |
| 2956 return SECFailure; | |
| 2957 } | |
| 2958 | |
| 2959 /* Sends out the initial client Hello message on the connection. | |
| 2960 * Acquires and releases the socket's xmitBufLock. | |
| 2961 */ | |
| 2962 SECStatus | |
| 2963 ssl2_BeginClientHandshake(sslSocket *ss) | |
| 2964 { | |
| 2965 sslSessionID *sid; | |
| 2966 PRUint8 *msg; | |
| 2967 PRUint8 *cp; | |
| 2968 PRUint8 *localCipherSpecs = NULL; | |
| 2969 unsigned int localCipherSize; | |
| 2970 unsigned int i; | |
| 2971 int sendLen, sidLen = 0; | |
| 2972 SECStatus rv; | |
| 2973 TLSExtensionData *xtnData; | |
| 2974 | |
| 2975 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 2976 | |
| 2977 ss->sec.isServer = 0; | |
| 2978 ss->sec.sendSequence = 0; | |
| 2979 ss->sec.rcvSequence = 0; | |
| 2980 ssl_ChooseSessionIDProcs(&ss->sec); | |
| 2981 | |
| 2982 if (!ss->cipherSpecs) { | |
| 2983 rv = ssl2_ConstructCipherSpecs(ss); | |
| 2984 if (rv != SECSuccess) | |
| 2985 goto loser; | |
| 2986 } | |
| 2987 | |
| 2988 /* count the SSL2 and SSL3 enabled ciphers. | |
| 2989 * if either is zero, clear the socket's enable for that protocol. | |
| 2990 */ | |
| 2991 rv = ssl2_CheckConfigSanity(ss); | |
| 2992 if (rv != SECSuccess) | |
| 2993 goto loser; | |
| 2994 | |
| 2995 /* Get peer name of server */ | |
| 2996 rv = ssl_GetPeerInfo(ss); | |
| 2997 if (rv < 0) { | |
| 2998 #ifdef HPUX11 | |
| 2999 /* | |
| 3000 * On some HP-UX B.11.00 systems, getpeername() occasionally | |
| 3001 * fails with ENOTCONN after a successful completion of | |
| 3002 * non-blocking connect. I found that if we do a write() | |
| 3003 * and then retry getpeername(), it will work. | |
| 3004 */ | |
| 3005 if (PR_GetError() == PR_NOT_CONNECTED_ERROR) { | |
| 3006 char dummy; | |
| 3007 (void) PR_Write(ss->fd->lower, &dummy, 0); | |
| 3008 rv = ssl_GetPeerInfo(ss); | |
| 3009 if (rv < 0) { | |
| 3010 goto loser; | |
| 3011 } | |
| 3012 } | |
| 3013 #else | |
| 3014 goto loser; | |
| 3015 #endif | |
| 3016 } | |
| 3017 | |
| 3018 SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd)); | |
| 3019 | |
| 3020 /* Try to find server in our session-id cache */ | |
| 3021 if (ss->opt.noCache) { | |
| 3022 sid = NULL; | |
| 3023 } else { | |
| 3024 sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, | |
| 3025 ss->url); | |
| 3026 } | |
| 3027 while (sid) { /* this isn't really a loop */ | |
| 3028 PRBool sidVersionEnabled = | |
| 3029 (!SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) && | |
| 3030 sid->version >= ss->vrange.min && | |
| 3031 sid->version <= ss->vrange.max) || | |
| 3032 (sid->version < SSL_LIBRARY_VERSION_3_0 && ss->opt.enableSSL2); | |
| 3033 | |
| 3034 /* if we're not doing this SID's protocol any more, drop it. */ | |
| 3035 if (!sidVersionEnabled) { | |
| 3036 if (ss->sec.uncache) | |
| 3037 ss->sec.uncache(sid); | |
| 3038 ssl_FreeSID(sid); | |
| 3039 sid = NULL; | |
| 3040 break; | |
| 3041 } | |
| 3042 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | |
| 3043 /* If the cipher in this sid is not enabled, drop it. */ | |
| 3044 for (i = 0; i < ss->sizeCipherSpecs; i += 3) { | |
| 3045 if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType) | |
| 3046 break; | |
| 3047 } | |
| 3048 if (i >= ss->sizeCipherSpecs) { | |
| 3049 if (ss->sec.uncache) | |
| 3050 ss->sec.uncache(sid); | |
| 3051 ssl_FreeSID(sid); | |
| 3052 sid = NULL; | |
| 3053 break; | |
| 3054 } | |
| 3055 } | |
| 3056 sidLen = sizeof(sid->u.ssl2.sessionID); | |
| 3057 PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl2.sessionID, | |
| 3058 sidLen)); | |
| 3059 ss->version = sid->version; | |
| 3060 PORT_Assert(!ss->sec.localCert); | |
| 3061 if (ss->sec.localCert) { | |
| 3062 CERT_DestroyCertificate(ss->sec.localCert); | |
| 3063 } | |
| 3064 ss->sec.localCert = CERT_DupCertificate(sid->localCert); | |
| 3065 break; /* this isn't really a loop */ | |
| 3066 } | |
| 3067 if (!sid) { | |
| 3068 sidLen = 0; | |
| 3069 sid = PORT_ZNew(sslSessionID); | |
| 3070 if (!sid) { | |
| 3071 goto loser; | |
| 3072 } | |
| 3073 sid->references = 1; | |
| 3074 sid->cached = never_cached; | |
| 3075 sid->addr = ss->sec.ci.peer; | |
| 3076 sid->port = ss->sec.ci.port; | |
| 3077 if (ss->peerID != NULL) { | |
| 3078 sid->peerID = PORT_Strdup(ss->peerID); | |
| 3079 } | |
| 3080 if (ss->url != NULL) { | |
| 3081 sid->urlSvrName = PORT_Strdup(ss->url); | |
| 3082 } | |
| 3083 } | |
| 3084 ss->sec.ci.sid = sid; | |
| 3085 | |
| 3086 PORT_Assert(sid != NULL); | |
| 3087 | |
| 3088 if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->opt.v2CompatibleHello)
&& | |
| 3089 !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { | |
| 3090 ss->gs.state = GS_INIT; | |
| 3091 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 3092 | |
| 3093 /* ssl3_SendClientHello will override this if it succeeds. */ | |
| 3094 ss->version = SSL_LIBRARY_VERSION_3_0; | |
| 3095 | |
| 3096 ssl_GetSSL3HandshakeLock(ss); | |
| 3097 ssl_GetXmitBufLock(ss); | |
| 3098 rv = ssl3_SendClientHello(ss, PR_FALSE); | |
| 3099 ssl_ReleaseXmitBufLock(ss); | |
| 3100 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 3101 | |
| 3102 return rv; | |
| 3103 } | |
| 3104 #if defined(NSS_ENABLE_ECC) | |
| 3105 /* ensure we don't neogtiate ECC cipher suites with SSL2 hello */ | |
| 3106 ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */ | |
| 3107 if (ss->cipherSpecs != NULL) { | |
| 3108 PORT_Free(ss->cipherSpecs); | |
| 3109 ss->cipherSpecs = NULL; | |
| 3110 ss->sizeCipherSpecs = 0; | |
| 3111 } | |
| 3112 #endif | |
| 3113 | |
| 3114 if (!ss->cipherSpecs) { | |
| 3115 rv = ssl2_ConstructCipherSpecs(ss); | |
| 3116 if (rv < 0) { | |
| 3117 return rv; | |
| 3118 } | |
| 3119 } | |
| 3120 localCipherSpecs = ss->cipherSpecs; | |
| 3121 localCipherSize = ss->sizeCipherSpecs; | |
| 3122 | |
| 3123 /* Add 3 for SCSV */ | |
| 3124 sendLen = SSL_HL_CLIENT_HELLO_HBYTES + localCipherSize + 3 + sidLen + | |
| 3125 SSL_CHALLENGE_BYTES; | |
| 3126 | |
| 3127 /* Generate challenge bytes for server */ | |
| 3128 PK11_GenerateRandom(ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES); | |
| 3129 | |
| 3130 ssl_GetXmitBufLock(ss); /***************************************/ | |
| 3131 | |
| 3132 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 3133 if (rv) | |
| 3134 goto unlock_loser; | |
| 3135 | |
| 3136 /* Construct client-hello message */ | |
| 3137 cp = msg = ss->sec.ci.sendBuf.buf; | |
| 3138 msg[0] = SSL_MT_CLIENT_HELLO; | |
| 3139 ss->clientHelloVersion = SSL3_ALL_VERSIONS_DISABLED(&ss->vrange) ? | |
| 3140 SSL_LIBRARY_VERSION_2 : ss->vrange.max; | |
| 3141 | |
| 3142 msg[1] = MSB(ss->clientHelloVersion); | |
| 3143 msg[2] = LSB(ss->clientHelloVersion); | |
| 3144 /* Add 3 for SCSV */ | |
| 3145 msg[3] = MSB(localCipherSize + 3); | |
| 3146 msg[4] = LSB(localCipherSize + 3); | |
| 3147 msg[5] = MSB(sidLen); | |
| 3148 msg[6] = LSB(sidLen); | |
| 3149 msg[7] = MSB(SSL_CHALLENGE_BYTES); | |
| 3150 msg[8] = LSB(SSL_CHALLENGE_BYTES); | |
| 3151 cp += SSL_HL_CLIENT_HELLO_HBYTES; | |
| 3152 PORT_Memcpy(cp, localCipherSpecs, localCipherSize); | |
| 3153 cp += localCipherSize; | |
| 3154 /* | |
| 3155 * Add SCSV. SSL 2.0 cipher suites are listed before SSL 3.0 cipher | |
| 3156 * suites in localCipherSpecs for compatibility with SSL 2.0 servers. | |
| 3157 * Since SCSV looks like an SSL 3.0 cipher suite, we can't add it at | |
| 3158 * the beginning. | |
| 3159 */ | |
| 3160 cp[0] = 0x00; | |
| 3161 cp[1] = 0x00; | |
| 3162 cp[2] = 0xff; | |
| 3163 cp += 3; | |
| 3164 if (sidLen) { | |
| 3165 PORT_Memcpy(cp, sid->u.ssl2.sessionID, sidLen); | |
| 3166 cp += sidLen; | |
| 3167 } | |
| 3168 PORT_Memcpy(cp, ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES); | |
| 3169 | |
| 3170 /* Send it to the server */ | |
| 3171 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 3172 ss->handshakeBegun = 1; | |
| 3173 rv = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 3174 | |
| 3175 ssl_ReleaseXmitBufLock(ss); /***************************************/ | |
| 3176 | |
| 3177 if (rv < 0) { | |
| 3178 goto loser; | |
| 3179 } | |
| 3180 | |
| 3181 rv = ssl3_StartHandshakeHash(ss, msg, sendLen); | |
| 3182 if (rv < 0) { | |
| 3183 goto loser; | |
| 3184 } | |
| 3185 | |
| 3186 /* | |
| 3187 * Since we sent the SCSV, pretend we sent empty RI extension. We need | |
| 3188 * to record the extension has been advertised after ssl3_InitState has | |
| 3189 * been called, which ssl3_StartHandshakeHash took care for us above. | |
| 3190 */ | |
| 3191 xtnData = &ss->xtnData; | |
| 3192 xtnData->advertised[xtnData->numAdvertised++] = ssl_renegotiation_info_xtn; | |
| 3193 | |
| 3194 /* Setup to receive servers hello message */ | |
| 3195 ssl_GetRecvBufLock(ss); | |
| 3196 ss->gs.recordLen = 0; | |
| 3197 ssl_ReleaseRecvBufLock(ss); | |
| 3198 | |
| 3199 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 3200 ss->nextHandshake = ssl2_HandleServerHelloMessage; | |
| 3201 return SECSuccess; | |
| 3202 | |
| 3203 unlock_loser: | |
| 3204 ssl_ReleaseXmitBufLock(ss); | |
| 3205 loser: | |
| 3206 return SECFailure; | |
| 3207 } | |
| 3208 | |
| 3209 /************************************************************************/ | |
| 3210 | |
| 3211 /* Handle the CLIENT-MASTER-KEY message. | |
| 3212 ** Acquires and releases RecvBufLock. | |
| 3213 ** Called from ssl2_HandleClientHelloMessage(). | |
| 3214 */ | |
| 3215 static SECStatus | |
| 3216 ssl2_HandleClientSessionKeyMessage(sslSocket *ss) | |
| 3217 { | |
| 3218 PRUint8 * data; | |
| 3219 unsigned int caLen; | |
| 3220 unsigned int ckLen; | |
| 3221 unsigned int ekLen; | |
| 3222 unsigned int keyBits; | |
| 3223 int cipher; | |
| 3224 SECStatus rv; | |
| 3225 | |
| 3226 | |
| 3227 ssl_GetRecvBufLock(ss); | |
| 3228 | |
| 3229 data = ss->gs.buf.buf + ss->gs.recordOffset; | |
| 3230 DUMP_MSG(29, (ss, data, ss->gs.recordLen)); | |
| 3231 | |
| 3232 if ((ss->gs.recordLen < SSL_HL_CLIENT_MASTER_KEY_HBYTES) | |
| 3233 || (data[0] != SSL_MT_CLIENT_MASTER_KEY)) { | |
| 3234 goto bad_client; | |
| 3235 } | |
| 3236 cipher = data[1]; | |
| 3237 keyBits = (data[2] << 8) | data[3]; | |
| 3238 ckLen = (data[4] << 8) | data[5]; | |
| 3239 ekLen = (data[6] << 8) | data[7]; | |
| 3240 caLen = (data[8] << 8) | data[9]; | |
| 3241 | |
| 3242 SSL_TRC(5, ("%d: SSL[%d]: session-key, cipher=%d keyBits=%d ckLen=%d ekLen=%
d caLen=%d", | |
| 3243 SSL_GETPID(), ss->fd, cipher, keyBits, ckLen, ekLen, caLen)); | |
| 3244 | |
| 3245 if (ss->gs.recordLen < | |
| 3246 SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen + caLen) { | |
| 3247 SSL_DBG(("%d: SSL[%d]: protocol size mismatch dataLen=%d", | |
| 3248 SSL_GETPID(), ss->fd, ss->gs.recordLen)); | |
| 3249 goto bad_client; | |
| 3250 } | |
| 3251 | |
| 3252 /* Use info from client to setup session key */ | |
| 3253 rv = ssl2_ServerSetupSessionCypher(ss, cipher, keyBits, | |
| 3254 data + SSL_HL_CLIENT_MASTER_KEY_HBYTES, ckLen, | |
| 3255 data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen, ekLen, | |
| 3256 data + SSL_HL_CLIENT_MASTER_KEY_HBYTES + ckLen + ekLen, caLen); | |
| 3257 ss->gs.recordLen = 0; /* we're done with this record. */ | |
| 3258 | |
| 3259 ssl_ReleaseRecvBufLock(ss); | |
| 3260 | |
| 3261 if (rv != SECSuccess) { | |
| 3262 goto loser; | |
| 3263 } | |
| 3264 ss->sec.ci.elements |= CIS_HAVE_MASTER_KEY; | |
| 3265 ssl2_UseEncryptedSendFunc(ss); | |
| 3266 | |
| 3267 /* Send server verify message now that keys are established */ | |
| 3268 rv = ssl2_SendServerVerifyMessage(ss); | |
| 3269 if (rv != SECSuccess) | |
| 3270 goto loser; | |
| 3271 | |
| 3272 rv = ssl2_TryToFinish(ss); | |
| 3273 if (rv != SECSuccess) | |
| 3274 goto loser; | |
| 3275 if (ss->handshake == 0) { | |
| 3276 return SECSuccess; | |
| 3277 } | |
| 3278 | |
| 3279 SSL_TRC(5, ("%d: SSL[%d]: server: waiting for elements=0x%d", | |
| 3280 SSL_GETPID(), ss->fd, | |
| 3281 ss->sec.ci.requiredElements ^ ss->sec.ci.elements)); | |
| 3282 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 3283 ss->nextHandshake = ssl2_HandleMessage; | |
| 3284 | |
| 3285 return ssl2_TriggerNextMessage(ss); | |
| 3286 | |
| 3287 bad_client: | |
| 3288 ssl_ReleaseRecvBufLock(ss); | |
| 3289 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 3290 /* FALLTHROUGH */ | |
| 3291 | |
| 3292 loser: | |
| 3293 return SECFailure; | |
| 3294 } | |
| 3295 | |
| 3296 /* | |
| 3297 ** Handle the initial hello message from the client | |
| 3298 ** | |
| 3299 ** not static because ssl2_GatherData() tests ss->nextHandshake for this value. | |
| 3300 */ | |
| 3301 SECStatus | |
| 3302 ssl2_HandleClientHelloMessage(sslSocket *ss) | |
| 3303 { | |
| 3304 sslSessionID *sid; | |
| 3305 sslServerCerts * sc; | |
| 3306 CERTCertificate *serverCert; | |
| 3307 PRUint8 *msg; | |
| 3308 PRUint8 *data; | |
| 3309 PRUint8 *cs; | |
| 3310 PRUint8 *sd; | |
| 3311 PRUint8 *cert = NULL; | |
| 3312 PRUint8 *challenge; | |
| 3313 unsigned int challengeLen; | |
| 3314 SECStatus rv; | |
| 3315 int csLen; | |
| 3316 int sendLen; | |
| 3317 int sdLen; | |
| 3318 int certLen; | |
| 3319 int pid; | |
| 3320 int sent; | |
| 3321 int gotXmitBufLock = 0; | |
| 3322 #if defined(SOLARIS) && defined(i386) | |
| 3323 volatile PRUint8 hit; | |
| 3324 #else | |
| 3325 int hit; | |
| 3326 #endif | |
| 3327 PRUint8 csImpl[sizeof implementedCipherSuites]; | |
| 3328 | |
| 3329 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 3330 | |
| 3331 sc = ss->serverCerts + kt_rsa; | |
| 3332 serverCert = sc->serverCert; | |
| 3333 | |
| 3334 ssl_GetRecvBufLock(ss); | |
| 3335 | |
| 3336 | |
| 3337 data = ss->gs.buf.buf + ss->gs.recordOffset; | |
| 3338 DUMP_MSG(29, (ss, data, ss->gs.recordLen)); | |
| 3339 | |
| 3340 /* Make sure first message has some data and is the client hello message */ | |
| 3341 if ((ss->gs.recordLen < SSL_HL_CLIENT_HELLO_HBYTES) | |
| 3342 || (data[0] != SSL_MT_CLIENT_HELLO)) { | |
| 3343 goto bad_client; | |
| 3344 } | |
| 3345 | |
| 3346 /* Get peer name of client */ | |
| 3347 rv = ssl_GetPeerInfo(ss); | |
| 3348 if (rv != SECSuccess) { | |
| 3349 goto loser; | |
| 3350 } | |
| 3351 | |
| 3352 /* Examine version information */ | |
| 3353 /* | |
| 3354 * See if this might be a V2 client hello asking to use the V3 protocol | |
| 3355 */ | |
| 3356 if ((data[0] == SSL_MT_CLIENT_HELLO) && | |
| 3357 (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) && | |
| 3358 !SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { | |
| 3359 rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen); | |
| 3360 if (rv != SECFailure) { /* Success */ | |
| 3361 ss->handshake = NULL; | |
| 3362 ss->nextHandshake = ssl_GatherRecord1stHandshake; | |
| 3363 ss->securityHandshake = NULL; | |
| 3364 ss->gs.state = GS_INIT; | |
| 3365 | |
| 3366 /* ssl3_HandleV3ClientHello has set ss->version, | |
| 3367 ** and has gotten us a brand new sid. | |
| 3368 */ | |
| 3369 ss->sec.ci.sid->version = ss->version; | |
| 3370 } | |
| 3371 ssl_ReleaseRecvBufLock(ss); | |
| 3372 return rv; | |
| 3373 } | |
| 3374 /* Previously, there was a test here to see if SSL2 was enabled. | |
| 3375 ** If not, an error code was set, and SECFailure was returned, | |
| 3376 ** without sending any error code to the other end of the connection. | |
| 3377 ** That test has been removed. If SSL2 has been disabled, there | |
| 3378 ** should be no SSL2 ciphers enabled, and consequently, the code | |
| 3379 ** below should send the ssl2 error message SSL_PE_NO_CYPHERS. | |
| 3380 ** We now believe this is the correct thing to do, even when SSL2 | |
| 3381 ** has been explicitly disabled by the application. | |
| 3382 */ | |
| 3383 | |
| 3384 /* Extract info from message */ | |
| 3385 ss->version = (data[1] << 8) | data[2]; | |
| 3386 | |
| 3387 /* If some client thinks ssl v2 is 2.0 instead of 0.2, we'll allow it. */ | |
| 3388 if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 3389 ss->version = SSL_LIBRARY_VERSION_2; | |
| 3390 } | |
| 3391 | |
| 3392 csLen = (data[3] << 8) | data[4]; | |
| 3393 sdLen = (data[5] << 8) | data[6]; | |
| 3394 challengeLen = (data[7] << 8) | data[8]; | |
| 3395 cs = data + SSL_HL_CLIENT_HELLO_HBYTES; | |
| 3396 sd = cs + csLen; | |
| 3397 challenge = sd + sdLen; | |
| 3398 PRINT_BUF(7, (ss, "server, client session-id value:", sd, sdLen)); | |
| 3399 | |
| 3400 if (!csLen || (csLen % 3) != 0 || | |
| 3401 (sdLen != 0 && sdLen != SSL2_SESSIONID_BYTES) || | |
| 3402 challengeLen < SSL_MIN_CHALLENGE_BYTES || | |
| 3403 challengeLen > SSL_MAX_CHALLENGE_BYTES || | |
| 3404 (unsigned)ss->gs.recordLen != | |
| 3405 SSL_HL_CLIENT_HELLO_HBYTES + csLen + sdLen + challengeLen) { | |
| 3406 SSL_DBG(("%d: SSL[%d]: bad client hello message, len=%d should=%d", | |
| 3407 SSL_GETPID(), ss->fd, ss->gs.recordLen, | |
| 3408 SSL_HL_CLIENT_HELLO_HBYTES+csLen+sdLen+challengeLen)); | |
| 3409 goto bad_client; | |
| 3410 } | |
| 3411 | |
| 3412 SSL_TRC(3, ("%d: SSL[%d]: client version is %x", | |
| 3413 SSL_GETPID(), ss->fd, ss->version)); | |
| 3414 if (ss->version != SSL_LIBRARY_VERSION_2) { | |
| 3415 if (ss->version > SSL_LIBRARY_VERSION_2) { | |
| 3416 /* | |
| 3417 ** Newer client than us. Things are ok because new clients | |
| 3418 ** are required to be backwards compatible with old servers. | |
| 3419 ** Change version number to our version number so that client | |
| 3420 ** knows whats up. | |
| 3421 */ | |
| 3422 ss->version = SSL_LIBRARY_VERSION_2; | |
| 3423 } else { | |
| 3424 SSL_TRC(1, ("%d: SSL[%d]: client version is %x (we are %x)", | |
| 3425 SSL_GETPID(), ss->fd, ss->version, SSL_LIBRARY_VERSION_2)); | |
| 3426 PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION); | |
| 3427 goto loser; | |
| 3428 } | |
| 3429 } | |
| 3430 | |
| 3431 /* Qualify cipher specs before returning them to client */ | |
| 3432 csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen); | |
| 3433 if (csLen == 0) { | |
| 3434 /* no overlap, send client our list of supported SSL v2 ciphers. */ | |
| 3435 cs = csImpl; | |
| 3436 csLen = sizeof implementedCipherSuites; | |
| 3437 PORT_Memcpy(cs, implementedCipherSuites, csLen); | |
| 3438 csLen = ssl2_QualifyCypherSpecs(ss, cs, csLen); | |
| 3439 if (csLen == 0) { | |
| 3440 /* We don't support any SSL v2 ciphers! */ | |
| 3441 ssl2_SendErrorMessage(ss, SSL_PE_NO_CYPHERS); | |
| 3442 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 3443 goto loser; | |
| 3444 } | |
| 3445 /* Since this handhsake is going to fail, don't cache it. */ | |
| 3446 ss->opt.noCache = 1; | |
| 3447 } | |
| 3448 | |
| 3449 /* Squirrel away the challenge for later */ | |
| 3450 PORT_Memcpy(ss->sec.ci.clientChallenge, challenge, challengeLen); | |
| 3451 | |
| 3452 /* Examine message and see if session-id is good */ | |
| 3453 ss->sec.ci.elements = 0; | |
| 3454 if (sdLen > 0 && !ss->opt.noCache) { | |
| 3455 SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08
x%08x%08x", | |
| 3456 SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], | |
| 3457 ss->sec.ci.peer.pr_s6_addr32[1], | |
| 3458 ss->sec.ci.peer.pr_s6_addr32[2], | |
| 3459 ss->sec.ci.peer.pr_s6_addr32[3])); | |
| 3460 sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sd, sdLen, ss->dbHandle); | |
| 3461 } else { | |
| 3462 sid = NULL; | |
| 3463 } | |
| 3464 if (sid) { | |
| 3465 /* Got a good session-id. Short cut! */ | |
| 3466 SSL_TRC(1, ("%d: SSL[%d]: server, using session-id for 0x%08x (age=%d)", | |
| 3467 SSL_GETPID(), ss->fd, ss->sec.ci.peer, | |
| 3468 ssl_Time() - sid->creationTime)); | |
| 3469 PRINT_BUF(1, (ss, "session-id value:", sd, sdLen)); | |
| 3470 ss->sec.ci.sid = sid; | |
| 3471 ss->sec.ci.elements = CIS_HAVE_MASTER_KEY; | |
| 3472 hit = 1; | |
| 3473 certLen = 0; | |
| 3474 csLen = 0; | |
| 3475 | |
| 3476 ss->sec.authAlgorithm = sid->authAlgorithm; | |
| 3477 ss->sec.authKeyBits = sid->authKeyBits; | |
| 3478 ss->sec.keaType = sid->keaType; | |
| 3479 ss->sec.keaKeyBits = sid->keaKeyBits; | |
| 3480 | |
| 3481 rv = ssl2_CreateSessionCypher(ss, sid, PR_FALSE); | |
| 3482 if (rv != SECSuccess) { | |
| 3483 goto loser; | |
| 3484 } | |
| 3485 } else { | |
| 3486 SECItem * derCert = &serverCert->derCert; | |
| 3487 | |
| 3488 SSL_TRC(7, ("%d: SSL[%d]: server, lookup nonce missed", | |
| 3489 SSL_GETPID(), ss->fd)); | |
| 3490 if (!serverCert) { | |
| 3491 SET_ERROR_CODE | |
| 3492 goto loser; | |
| 3493 } | |
| 3494 hit = 0; | |
| 3495 sid = PORT_ZNew(sslSessionID); | |
| 3496 if (!sid) { | |
| 3497 goto loser; | |
| 3498 } | |
| 3499 sid->references = 1; | |
| 3500 sid->addr = ss->sec.ci.peer; | |
| 3501 sid->port = ss->sec.ci.port; | |
| 3502 | |
| 3503 /* Invent a session-id */ | |
| 3504 ss->sec.ci.sid = sid; | |
| 3505 PK11_GenerateRandom(sid->u.ssl2.sessionID+2, SSL2_SESSIONID_BYTES-2); | |
| 3506 | |
| 3507 pid = SSL_GETPID(); | |
| 3508 sid->u.ssl2.sessionID[0] = MSB(pid); | |
| 3509 sid->u.ssl2.sessionID[1] = LSB(pid); | |
| 3510 cert = derCert->data; | |
| 3511 certLen = derCert->len; | |
| 3512 | |
| 3513 /* pretend that server sids remember the local cert. */ | |
| 3514 PORT_Assert(!sid->localCert); | |
| 3515 if (sid->localCert) { | |
| 3516 CERT_DestroyCertificate(sid->localCert); | |
| 3517 } | |
| 3518 sid->localCert = CERT_DupCertificate(serverCert); | |
| 3519 | |
| 3520 ss->sec.authAlgorithm = ssl_sign_rsa; | |
| 3521 ss->sec.keaType = ssl_kea_rsa; | |
| 3522 ss->sec.keaKeyBits = \ | |
| 3523 ss->sec.authKeyBits = ss->serverCerts[kt_rsa].serverKeyBits; | |
| 3524 } | |
| 3525 | |
| 3526 /* server sids don't remember the local cert, so whether we found | |
| 3527 ** a sid or not, just "remember" we used the rsa server cert. | |
| 3528 */ | |
| 3529 if (ss->sec.localCert) { | |
| 3530 CERT_DestroyCertificate(ss->sec.localCert); | |
| 3531 } | |
| 3532 ss->sec.localCert = CERT_DupCertificate(serverCert); | |
| 3533 | |
| 3534 /* Build up final list of required elements */ | |
| 3535 ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED; | |
| 3536 if (ss->opt.requestCertificate) { | |
| 3537 ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE; | |
| 3538 } | |
| 3539 ss->sec.ci.sentElements = 0; | |
| 3540 | |
| 3541 /* Send hello message back to client */ | |
| 3542 sendLen = SSL_HL_SERVER_HELLO_HBYTES + certLen + csLen | |
| 3543 + SSL_CONNECTIONID_BYTES; | |
| 3544 | |
| 3545 ssl_GetXmitBufLock(ss); gotXmitBufLock = 1; | |
| 3546 rv = ssl2_GetSendBuffer(ss, sendLen); | |
| 3547 if (rv != SECSuccess) { | |
| 3548 goto loser; | |
| 3549 } | |
| 3550 | |
| 3551 SSL_TRC(3, ("%d: SSL[%d]: sending server-hello (%d)", | |
| 3552 SSL_GETPID(), ss->fd, sendLen)); | |
| 3553 | |
| 3554 msg = ss->sec.ci.sendBuf.buf; | |
| 3555 msg[0] = SSL_MT_SERVER_HELLO; | |
| 3556 msg[1] = hit; | |
| 3557 msg[2] = SSL_CT_X509_CERTIFICATE; | |
| 3558 msg[3] = MSB(ss->version); | |
| 3559 msg[4] = LSB(ss->version); | |
| 3560 msg[5] = MSB(certLen); | |
| 3561 msg[6] = LSB(certLen); | |
| 3562 msg[7] = MSB(csLen); | |
| 3563 msg[8] = LSB(csLen); | |
| 3564 msg[9] = MSB(SSL_CONNECTIONID_BYTES); | |
| 3565 msg[10] = LSB(SSL_CONNECTIONID_BYTES); | |
| 3566 if (certLen) { | |
| 3567 PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES, cert, certLen); | |
| 3568 } | |
| 3569 if (csLen) { | |
| 3570 PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen, cs, csLen); | |
| 3571 } | |
| 3572 PORT_Memcpy(msg+SSL_HL_SERVER_HELLO_HBYTES+certLen+csLen, | |
| 3573 ss->sec.ci.connectionID, SSL_CONNECTIONID_BYTES); | |
| 3574 | |
| 3575 DUMP_MSG(29, (ss, msg, sendLen)); | |
| 3576 | |
| 3577 ss->handshakeBegun = 1; | |
| 3578 sent = (*ss->sec.send)(ss, msg, sendLen, 0); | |
| 3579 if (sent < 0) { | |
| 3580 goto loser; | |
| 3581 } | |
| 3582 ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0; | |
| 3583 | |
| 3584 ss->gs.recordLen = 0; | |
| 3585 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 3586 if (hit) { | |
| 3587 /* Old SID Session key is good. Go encrypted */ | |
| 3588 ssl2_UseEncryptedSendFunc(ss); | |
| 3589 | |
| 3590 /* Send server verify message now that keys are established */ | |
| 3591 rv = ssl2_SendServerVerifyMessage(ss); | |
| 3592 if (rv != SECSuccess) | |
| 3593 goto loser; | |
| 3594 | |
| 3595 ss->nextHandshake = ssl2_HandleMessage; | |
| 3596 ssl_ReleaseRecvBufLock(ss); | |
| 3597 rv = ssl2_TriggerNextMessage(ss); | |
| 3598 return rv; | |
| 3599 } | |
| 3600 ss->nextHandshake = ssl2_HandleClientSessionKeyMessage; | |
| 3601 ssl_ReleaseRecvBufLock(ss); | |
| 3602 return SECSuccess; | |
| 3603 | |
| 3604 bad_client: | |
| 3605 PORT_SetError(SSL_ERROR_BAD_CLIENT); | |
| 3606 /* FALLTHROUGH */ | |
| 3607 | |
| 3608 loser: | |
| 3609 if (gotXmitBufLock) { | |
| 3610 ssl_ReleaseXmitBufLock(ss); gotXmitBufLock = 0; | |
| 3611 } | |
| 3612 SSL_TRC(10, ("%d: SSL[%d]: server, wait for client-hello lossage", | |
| 3613 SSL_GETPID(), ss->fd)); | |
| 3614 ssl_ReleaseRecvBufLock(ss); | |
| 3615 return SECFailure; | |
| 3616 } | |
| 3617 | |
| 3618 SECStatus | |
| 3619 ssl2_BeginServerHandshake(sslSocket *ss) | |
| 3620 { | |
| 3621 SECStatus rv; | |
| 3622 sslServerCerts * rsaAuth = ss->serverCerts + kt_rsa; | |
| 3623 | |
| 3624 ss->sec.isServer = 1; | |
| 3625 ssl_ChooseSessionIDProcs(&ss->sec); | |
| 3626 ss->sec.sendSequence = 0; | |
| 3627 ss->sec.rcvSequence = 0; | |
| 3628 | |
| 3629 /* don't turn on SSL2 if we don't have an RSA key and cert */ | |
| 3630 if (!rsaAuth->serverKeyPair || !rsaAuth->SERVERKEY || | |
| 3631 !rsaAuth->serverCert) { | |
| 3632 ss->opt.enableSSL2 = PR_FALSE; | |
| 3633 } | |
| 3634 | |
| 3635 if (!ss->cipherSpecs) { | |
| 3636 rv = ssl2_ConstructCipherSpecs(ss); | |
| 3637 if (rv != SECSuccess) | |
| 3638 goto loser; | |
| 3639 } | |
| 3640 | |
| 3641 /* count the SSL2 and SSL3 enabled ciphers. | |
| 3642 * if either is zero, clear the socket's enable for that protocol. | |
| 3643 */ | |
| 3644 rv = ssl2_CheckConfigSanity(ss); | |
| 3645 if (rv != SECSuccess) | |
| 3646 goto loser; | |
| 3647 | |
| 3648 /* | |
| 3649 ** Generate connection-id. Always do this, even if things fail | |
| 3650 ** immediately. This way the random number generator is always | |
| 3651 ** rolling around, every time we get a connection. | |
| 3652 */ | |
| 3653 PK11_GenerateRandom(ss->sec.ci.connectionID, | |
| 3654 sizeof(ss->sec.ci.connectionID)); | |
| 3655 | |
| 3656 ss->gs.recordLen = 0; | |
| 3657 ss->handshake = ssl_GatherRecord1stHandshake; | |
| 3658 ss->nextHandshake = ssl2_HandleClientHelloMessage; | |
| 3659 return SECSuccess; | |
| 3660 | |
| 3661 loser: | |
| 3662 return SECFailure; | |
| 3663 } | |
| 3664 | |
| 3665 /* This function doesn't really belong in this file. | |
| 3666 ** It's here to keep AIX compilers from optimizing it away, | |
| 3667 ** and not including it in the DSO. | |
| 3668 */ | |
| 3669 | |
| 3670 #include "nss.h" | |
| 3671 extern const char __nss_ssl_rcsid[]; | |
| 3672 extern const char __nss_ssl_sccsid[]; | |
| 3673 | |
| 3674 PRBool | |
| 3675 NSSSSL_VersionCheck(const char *importedVersion) | |
| 3676 { | |
| 3677 /* | |
| 3678 * This is the secret handshake algorithm. | |
| 3679 * | |
| 3680 * This release has a simple version compatibility | |
| 3681 * check algorithm. This release is not backward | |
| 3682 * compatible with previous major releases. It is | |
| 3683 * not compatible with future major, minor, or | |
| 3684 * patch releases. | |
| 3685 */ | |
| 3686 volatile char c; /* force a reference that won't get optimized away */ | |
| 3687 | |
| 3688 c = __nss_ssl_rcsid[0] + __nss_ssl_sccsid[0]; | |
| 3689 return NSS_VersionCheck(importedVersion); | |
| 3690 } | |
| 3691 | |
| 3692 const char * | |
| 3693 NSSSSL_GetVersion(void) | |
| 3694 { | |
| 3695 return NSS_VERSION; | |
| 3696 } | |
| OLD | NEW |