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