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