]> git.saurik.com Git - apple/security.git/blob - SecureTransport/ssltrspt.c
Security-54.1.tar.gz
[apple/security.git] / SecureTransport / ssltrspt.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: ssltrspt.c
21
22 Contains: SSLContext transport layer
23
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: ssltrspt.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: ssltrspt.c Data transportation functionality
47
48 Transports data between the application and the record layer; also
49 hands off handshake, alert, and change cipher spec messages to their
50 handlers. Also, ensures that negotiation happens before application
51 data goes out on the wire.
52
53 ****************************************************************** */
54
55 #ifndef _SSLTRSPT_H_
56 #include "ssltrspt.h"
57 #endif
58
59 #ifndef _SSLALLOC_H_
60 #include "sslalloc.h"
61 #endif
62
63 #ifndef _SSLCTX_H_
64 #include "sslctx.h"
65 #endif
66
67 #ifndef _SSLCTX_H_
68 #include "sslrec.h"
69 #endif
70
71 #ifndef _SSLALERT_H_
72 #include "sslalert.h"
73 #endif
74
75 #ifndef _SSLSESS_H_
76 #include "sslsess.h"
77 #endif
78
79 #ifndef _SSL2_H_
80 #include "ssl2.h"
81 #endif
82
83 #ifndef _APPLE_GLUE_H_
84 #include "appleGlue.h"
85 #endif
86
87 #ifndef _SSL_DEBUG_H_
88 #include "sslDebug.h"
89 #endif
90
91 #ifndef _CIPHER_SPECS_H_
92 #include "cipherSpecs.h"
93 #endif
94
95 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
96
97 #include <assert.h>
98 #include <string.h>
99
100 #define SSL_IO_TRACE 0
101 #if SSL_IO_TRACE
102 static void sslIoTrace(
103 const char *op,
104 UInt32 req,
105 UInt32 moved,
106 OSStatus stat)
107 {
108 printf("===%s: req %4d moved %4d status %d\n",
109 op, req, moved, stat);
110 }
111
112 #else
113 #define sslIoTrace(op, req, moved, stat)
114 #endif /* SSL_IO_TRACE */
115
116 static SSLErr SSLProcessProtocolMessage(SSLRecord rec, SSLContext *ctx);
117 static SSLErr SSLHandshakeProceed(SSLContext *ctx);
118 static SSLErr SSLInitConnection(SSLContext *ctx);
119 static SSLErr SSLServiceWriteQueue(SSLContext *ctx);
120
121 OSStatus
122 SSLWrite(
123 SSLContext *ctx,
124 const void * data,
125 UInt32 dataLength,
126 UInt32 *bytesWritten) /* RETURNED */
127 {
128 SSLErr err;
129 SSLRecord rec;
130 UInt32 dataLen, processed;
131
132 if((ctx == NULL) || (bytesWritten == NULL)) {
133 return paramErr;
134 }
135 dataLen = dataLength;
136 processed = 0; /* Initialize in case we return with SSLWouldBlockErr */
137 *bytesWritten = 0;
138
139 switch(ctx->state) {
140 case SSLGracefulClose:
141 err = SSLConnectionClosedGraceful;
142 goto abort;
143 case SSLErrorClose:
144 err = SSLConnectionClosedError;
145 goto abort;
146 default:
147 /* FIXME - original code didn't check for handshake in progress -
148 * should we?
149 */
150 sslIoTrace("SSLWrite", dataLength, 0, badReqErr);
151 return badReqErr;
152 case HandshakeServerReady:
153 case HandshakeClientReady:
154 break;
155 }
156
157 /* First, we have to wait until the session is ready to send data,
158 so the encryption keys and such have been established. */
159 err = SSLNoErr;
160 while (ctx->writeCipher.ready == 0)
161 { if ((err = SSLHandshakeProceed(ctx)) != 0)
162 goto exit;
163 }
164
165 /* Attempt to empty the write queue before queueing more data */
166 if ((err = SSLServiceWriteQueue(ctx)) != 0)
167 goto abort;
168
169 processed = 0;
170 /* Fragment, package and encrypt the data and queue the resulting data for sending */
171 while (dataLen > 0)
172 { rec.contentType = SSL_application_data;
173 rec.protocolVersion = ctx->negProtocolVersion;
174 rec.contents.data = ((UInt8*)data) + processed;
175
176 if (dataLen < MAX_RECORD_LENGTH)
177 rec.contents.length = dataLen;
178 else
179 rec.contents.length = MAX_RECORD_LENGTH;
180
181 assert(ctx->sslTslCalls != NULL);
182 if (ERR(err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
183 goto exit;
184
185 processed += rec.contents.length;
186 dataLen -= rec.contents.length;
187 }
188
189 /* All the data has been advanced to the write queue */
190 *bytesWritten = processed;
191 if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
192 goto exit;
193
194 err = SSLNoErr;
195 exit:
196 if (err != 0 && err != SSLWouldBlockErr && err != SSLConnectionClosedGraceful) {
197 dprintf1("SSLWrite: going to state errorCLose due to err %d\n",
198 err);
199 SSLChangeHdskState(ctx, SSLErrorClose);
200 }
201 abort:
202 sslIoTrace("SSLWrite", dataLength, *bytesWritten, sslErrToOsStatus(err));
203 return sslErrToOsStatus(err);
204 }
205
206 OSStatus
207 SSLRead (
208 SSLContext *ctx,
209 void * data,
210 UInt32 dataLength,
211 UInt32 *processed) /* RETURNED */
212 {
213 SSLErr err;
214 UInt8 *progress;
215 UInt32 bufSize, remaining, count;
216 SSLRecord rec;
217
218 if((ctx == NULL) || (processed == NULL)) {
219 return paramErr;
220 }
221 bufSize = dataLength;
222 *processed = 0; /* Initialize in case we return with SSLWouldBlockErr */
223
224 /* first handle cases in which we know we're finished */
225 switch(ctx->state) {
226 case SSLGracefulClose:
227 err = SSLConnectionClosedGraceful;
228 goto abort;
229 case SSLErrorClose:
230 err = SSLConnectionClosedError;
231 goto abort;
232 case SSLNoNotifyClose:
233 err = SSLConnectionClosedNoNotify;
234 goto abort;
235 default:
236 break;
237 }
238
239 /* First, we have to wait until the session is ready to receive data,
240 so the encryption keys and such have been established. */
241 err = SSLNoErr;
242 while (ctx->readCipher.ready == 0)
243 { if (ERR(err = SSLHandshakeProceed(ctx)) != 0)
244 goto exit;
245 }
246
247 /* Attempt to service the write queue */
248 if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
249 { if (err != SSLWouldBlockErr)
250 goto exit;
251 err = SSLNoErr; /* Write blocking shouldn't stop attempts to read */
252 }
253
254 remaining = bufSize;
255 progress = (UInt8*)data;
256 if (ctx->receivedDataBuffer.data)
257 { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
258 if (count > bufSize)
259 count = bufSize;
260 memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count);
261 remaining -= count;
262 progress += count;
263 *processed += count;
264 ctx->receivedDataPos += count;
265 }
266
267 CASSERT(ctx->receivedDataPos <= ctx->receivedDataBuffer.length);
268 CASSERT(*processed + remaining == bufSize);
269 CASSERT(progress == ((UInt8*)data) + *processed);
270
271 if (ctx->receivedDataBuffer.data != 0 &&
272 ctx->receivedDataPos >= ctx->receivedDataBuffer.length)
273 { SSLFreeBuffer(&ctx->receivedDataBuffer, &ctx->sysCtx);
274 ctx->receivedDataBuffer.data = 0;
275 ctx->receivedDataPos = 0;
276 }
277
278 /*
279 * This while statement causes a hang when using nonblocking low-level I/O!
280 while (remaining > 0 && ctx->state != SSLGracefulClose)
281 ..what we really have to do is just return as soon as we read one
282 record. A performance hit in the nonblocking case, but that is
283 the only way this code can work in both modes...
284 */
285 if (remaining > 0 && ctx->state != SSLGracefulClose)
286 { CASSERT(ctx->receivedDataBuffer.data == 0);
287 if (ERR(err = SSLReadRecord(&rec, ctx)) != 0)
288 goto exit;
289
290 if (rec.contentType == SSL_application_data ||
291 rec.contentType == SSL_version_2_0_record)
292 { if (rec.contents.length <= remaining)
293 { memcpy(progress, rec.contents.data, rec.contents.length);
294 remaining -= rec.contents.length;
295 progress += rec.contents.length;
296 *processed += rec.contents.length;
297 /* COMPILER BUG!
298 * This:
299 * if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
300 * passes the address of rec to SSLFreeBuffer, not the address
301 * of the contents field (which should be offset 8 from the start
302 * of rec).
303 */
304 {
305 SSLBuffer *b = &rec.contents;
306 if (ERR(err = SSLFreeBuffer(b, &ctx->sysCtx)) != 0) {
307 goto exit;
308 }
309 }
310 }
311 else
312 { memcpy(progress, rec.contents.data, remaining);
313 progress += remaining;
314 *processed += remaining;
315 ctx->receivedDataBuffer = rec.contents;
316 ctx->receivedDataPos = remaining;
317 remaining = 0;
318 }
319 }
320 else
321 { if (ERR(err = SSLProcessProtocolMessage(rec, ctx)) != 0)
322 goto exit;
323 if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
324 goto exit;
325 }
326 }
327
328 err = SSLNoErr;
329
330 exit:
331 /* shut down on serious errors */
332 switch(err) {
333 case SSLNoErr:
334 case SSLWouldBlockErr:
335 case SSLConnectionClosedGraceful:
336 case SSLConnectionClosedNoNotify:
337 break;
338 default:
339 dprintf1("SSLRead: going to state errorClose due to err %d\n",
340 err);
341 SSLChangeHdskState(ctx, SSLErrorClose);
342 break;
343 }
344 abort:
345 sslIoTrace("SSLRead ", dataLength, *processed, sslErrToOsStatus(err));
346 return sslErrToOsStatus(err);
347 }
348
349 #if SSL_DEBUG
350 #include "appleCdsa.h"
351 #endif
352
353 OSStatus
354 SSLHandshake(SSLContext *ctx)
355 {
356 SSLErr err;
357
358 if(ctx == NULL) {
359 return paramErr;
360 }
361 if (ctx->state == SSLGracefulClose)
362 return sslErrToOsStatus(SSLConnectionClosedGraceful);
363 if (ctx->state == SSLErrorClose)
364 return sslErrToOsStatus(SSLConnectionClosedError);
365
366 if(ctx->protocolSide == SSL_ServerSide) {
367 /* some things the caller really has to have done by now... */
368 if((ctx->localCert == NULL) ||
369 (ctx->signingPrivKey == NULL) ||
370 (ctx->signingPubKey == NULL) ||
371 (ctx->signingKeyCsp == 0)) {
372 errorLog0("SSLHandshake: insufficient init\n");
373 return badReqErr;
374 }
375 }
376 if(ctx->validCipherSpecs == NULL) {
377 /* build list of legal cipherSpecs */
378 err = sslBuildCipherSpecArray(ctx);
379 if(err) {
380 return err;
381 }
382 }
383 err = SSLNoErr;
384 while (ctx->readCipher.ready == 0 || ctx->writeCipher.ready == 0)
385 { if (ERR(err = SSLHandshakeProceed(ctx)) != 0)
386 return sslErrToOsStatus(err);
387 }
388
389 /* one more flush at completion of successful handshake */
390 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
391 return sslErrToOsStatus(err);
392 }
393 return noErr;
394 }
395
396
397 static SSLErr
398 SSLHandshakeProceed(SSLContext *ctx)
399 { SSLErr err;
400 SSLRecord rec;
401
402 if (ctx->state == SSLUninitialized)
403 if (ERR(err = SSLInitConnection(ctx)) != 0)
404 return err;
405 if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
406 return err;
407 CASSERT(ctx->readCipher.ready == 0);
408 if (ERR(err = SSLReadRecord(&rec, ctx)) != 0)
409 return err;
410 if (ERR(err = SSLProcessProtocolMessage(rec, ctx)) != 0)
411 { SSLFreeBuffer(&rec.contents, &ctx->sysCtx);
412 return err;
413 }
414 if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
415 return err;
416
417 return SSLNoErr;
418 }
419
420 static SSLErr
421 SSLInitConnection(SSLContext *ctx)
422 { SSLErr err;
423
424 if (ctx->protocolSide == SSL_ClientSide) {
425 SSLChangeHdskState(ctx, HandshakeClientUninit);
426 }
427 else
428 { CASSERT(ctx->protocolSide == SSL_ServerSide);
429 SSLChangeHdskState(ctx, HandshakeServerUninit);
430 }
431
432 if (ctx->peerID.data != 0)
433 { ERR(SSLGetSessionData(&ctx->resumableSession, ctx));
434 /* Ignore errors; just treat as uncached session */
435 }
436
437 /*
438 * If we have a cached resumable session, blow it off if it's a higher
439 * version than the max currently allowed. Note that this means that once
440 * a process negotiates a given version with a given server/port, it won't
441 * be able to negotiate a higher version. We might want to revisit this.
442 */
443 if (ctx->resumableSession.data != 0) {
444
445 SSLProtocolVersion savedVersion;
446
447 if (ERR(err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession,
448 &savedVersion, ctx)) != 0) {
449 return err;
450 }
451 if(savedVersion > ctx->maxProtocolVersion) {
452 SSLLogResumSess("===Resumable session protocol mismatch\n");
453 SSLFreeBuffer(&ctx->resumableSession, &ctx->sysCtx);
454 }
455 else {
456 SSLLogResumSess("===attempting to resume session\n");
457 /*
458 * A bit of a special case for server side here. If currently
459 * configged to allow for SSL3/TLS1 with an SSL2 hello, we
460 * don't want to preclude the possiblity of an SSL2 hello...
461 * so we'll just leave the negProtocolVersion alone in the server case.
462 */
463 if(ctx->protocolSide == SSL_ClientSide) {
464 ctx->negProtocolVersion = savedVersion;
465 }
466 }
467 }
468
469 /* If we're the client & handshake hasn't yet begun, start it by
470 * pretending we just received a hello request
471 */
472 if (ctx->state == HandshakeClientUninit && ctx->writeCipher.ready == 0)
473 { switch (ctx->negProtocolVersion)
474 { case SSL_Version_Undetermined:
475 case SSL_Version_3_0_With_2_0_Hello:
476 case SSL_Version_2_0:
477 if (ERR(err = SSL2AdvanceHandshake(ssl2_mt_kickstart_handshake, ctx)) != 0)
478 return err;
479 break;
480 case SSL_Version_3_0_Only:
481 case SSL_Version_3_0:
482 case TLS_Version_1_0_Only:
483 case TLS_Version_1_0:
484 if (ERR(err = SSLAdvanceHandshake(SSL_hello_request, ctx)) != 0)
485 return err;
486 break;
487 default:
488 sslPanic("Bad protocol version");
489 break;
490 }
491 }
492
493 return SSLNoErr;
494 }
495
496 static SSLErr
497 SSLServiceWriteQueue(SSLContext *ctx)
498 { SSLErr err = SSLNoErr, werr = SSLNoErr;
499 UInt32 written = 0;
500 SSLBuffer buf, recBuf;
501 WaitingRecord *rec;
502
503 while (!werr && ((rec = ctx->recordWriteQueue) != 0))
504 { buf.data = rec->data.data + rec->sent;
505 buf.length = rec->data.length - rec->sent;
506 werr = sslIoWrite(buf, &written, ctx);
507 rec->sent += written;
508 if (rec->sent >= rec->data.length)
509 { CASSERT(rec->sent == rec->data.length);
510 CASSERT(err == 0);
511 err = SSLFreeBuffer(&rec->data, &ctx->sysCtx);
512 CASSERT(err == 0);
513 recBuf.data = (UInt8*)rec;
514 recBuf.length = sizeof(WaitingRecord);
515 ctx->recordWriteQueue = rec->next;
516 err = SSLFreeBuffer(&recBuf, &ctx->sysCtx);
517 CASSERT(err == 0);
518 }
519 if (ERR(err))
520 return err;
521 CASSERT(ctx->recordWriteQueue == 0 || ctx->recordWriteQueue->sent == 0);
522 }
523
524 return werr;
525 }
526
527 #if LOG_RX_PROTOCOL
528 static void sslLogRxProto(const char *msgType)
529 {
530 printf("---received protoMsg %s\n", msgType);
531 }
532 #else
533 #define sslLogRxProto(msgType)
534 #endif /* LOG_RX_PROTOCOL */
535
536 static SSLErr
537 SSLProcessProtocolMessage(SSLRecord rec, SSLContext *ctx)
538 { SSLErr err;
539
540 switch (rec.contentType)
541 { case SSL_handshake:
542 sslLogRxProto("SSL_handshake");
543 ERR(err = SSLProcessHandshakeRecord(rec, ctx));
544 break;
545 case SSL_alert:
546 sslLogRxProto("SSL_alert");
547 ERR(err = SSLProcessAlert(rec, ctx));
548 break;
549 case SSL_change_cipher_spec:
550 sslLogRxProto("SSL_change_cipher_spec");
551 ERR(err = SSLProcessChangeCipherSpec(rec, ctx));
552 break;
553 case SSL_version_2_0_record:
554 sslLogRxProto("SSL_version_2_0_record");
555 ERR(err = SSL2ProcessMessage(rec, ctx));
556 break;
557 default:
558 sslLogRxProto("Bad msg");
559 return ERR(SSLProtocolErr);
560 }
561
562 return err;
563 }
564
565 OSStatus
566 SSLClose(SSLContext *ctx)
567 {
568 SSLErr err = SSLNoErr;
569
570 if(ctx == NULL) {
571 return paramErr;
572 }
573 if (ctx->negProtocolVersion >= SSL_Version_3_0)
574 ERR(err = SSLSendAlert(alert_warning, alert_close_notify, ctx));
575 if (err == 0)
576 ERR(err = SSLServiceWriteQueue(ctx));
577 SSLChangeHdskState(ctx, SSLGracefulClose);
578 if (err == SSLIOErr)
579 err = SSLNoErr; /* Ignore errors related to closed streams */
580 return sslErrToOsStatus(err);
581 }
582
583 /*
584 * Determine how much data the client can be guaranteed to
585 * obtain via SSLRead() without blocking or causing any low-level
586 * read operations to occur.
587 *
588 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
589 * and receivedDataPos) are only used in this file.
590 */
591 OSStatus
592 SSLGetBufferedReadSize(SSLContextRef ctx,
593 size_t *bufSize) /* RETURNED */
594 {
595 if(ctx == NULL) {
596 return paramErr;
597 }
598 if(ctx->receivedDataBuffer.data == NULL) {
599 *bufSize = 0;
600 }
601 else {
602 CASSERT(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
603 *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
604 }
605 return noErr;
606 }