]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslTransport.cpp
1b352e432a035feb52e794ee1b552eff8af46887
[apple/security.git] / SecureTransport / sslTransport.cpp
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: sslTransport.c
21
22 Contains: SSL transport layer
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslMemory.h"
31 #include "sslContext.h"
32 #include "sslRecord.h"
33 #include "sslAlertMessage.h"
34 #include "sslSession.h"
35 #include "ssl2.h"
36 #include "sslDebug.h"
37 #include "cipherSpecs.h"
38 #include "sslUtils.h"
39
40 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
41
42 #include <assert.h>
43 #include <string.h>
44
45 #ifndef NDEBUG
46 static void inline sslIoTrace(
47 const char *op,
48 UInt32 req,
49 UInt32 moved,
50 OSStatus stat)
51 {
52 sslLogRecordIo("===%s: req %4lu moved %4lu status %ld",
53 op, req, moved, stat);
54 }
55 #else
56 #define sslIoTrace(op, req, moved, stat)
57 #endif /* NDEBUG */
58
59 static OSStatus SSLProcessProtocolMessage(SSLRecord &rec, SSLContext *ctx);
60 static OSStatus SSLHandshakeProceed(SSLContext *ctx);
61 static OSStatus SSLInitConnection(SSLContext *ctx);
62 static OSStatus SSLServiceWriteQueue(SSLContext *ctx);
63
64 OSStatus
65 SSLWrite(
66 SSLContext *ctx,
67 const void * data,
68 UInt32 dataLength,
69 UInt32 *bytesWritten) /* RETURNED */
70 {
71 OSStatus err;
72 SSLRecord rec;
73 UInt32 dataLen, processed;
74
75 sslLogRecordIo("SSLWrite top");
76 if((ctx == NULL) || (bytesWritten == NULL)) {
77 return paramErr;
78 }
79 dataLen = dataLength;
80 processed = 0; /* Initialize in case we return with errSSLWouldBlock */
81 *bytesWritten = 0;
82
83 switch(ctx->state) {
84 case SSL_HdskStateGracefulClose:
85 err = errSSLClosedGraceful;
86 goto abort;
87 case SSL_HdskStateErrorClose:
88 err = errSSLClosedAbort;
89 goto abort;
90 default:
91 /* FIXME - original code didn't check for pending handshake -
92 * should we?
93 */
94 sslIoTrace("SSLWrite", dataLength, 0, badReqErr);
95 return badReqErr;
96 case SSL_HdskStateServerReady:
97 case SSL_HdskStateClientReady:
98 break;
99 }
100
101 /* First, we have to wait until the session is ready to send data,
102 so the encryption keys and such have been established. */
103 err = noErr;
104 while (ctx->writeCipher.ready == 0)
105 { if ((err = SSLHandshakeProceed(ctx)) != 0)
106 goto exit;
107 }
108
109 /* Attempt to empty the write queue before queueing more data */
110 if ((err = SSLServiceWriteQueue(ctx)) != 0)
111 goto abort;
112
113 processed = 0;
114 /*
115 * Fragment, package and encrypt the data and queue the resulting data
116 * for sending
117 */
118 while (dataLen > 0)
119 { rec.contentType = SSL_RecordTypeAppData;
120 rec.protocolVersion = ctx->negProtocolVersion;
121 rec.contents.data = ((UInt8*)data) + processed;
122
123 if (dataLen < MAX_RECORD_LENGTH)
124 rec.contents.length = dataLen;
125 else
126 rec.contents.length = MAX_RECORD_LENGTH;
127
128 assert(ctx->sslTslCalls != NULL);
129 if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
130 goto exit;
131 processed += rec.contents.length;
132 dataLen -= rec.contents.length;
133 }
134
135 /* All the data has been advanced to the write queue */
136 *bytesWritten = processed;
137 if ((err = SSLServiceWriteQueue(ctx)) == 0) {
138 err = noErr;
139 }
140 exit:
141 if (err != 0 && err != errSSLWouldBlock && err != errSSLClosedGraceful) {
142 sslErrorLog("SSLWrite: going to state errorCLose due to err %d\n",
143 (int)err);
144 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
145 }
146 abort:
147 sslIoTrace("SSLWrite", dataLength, *bytesWritten, err);
148 return err;
149 }
150
151 OSStatus
152 SSLRead (
153 SSLContext *ctx,
154 void * data,
155 UInt32 dataLength,
156 UInt32 *processed) /* RETURNED */
157 {
158 OSStatus err;
159 UInt8 *charPtr;
160 UInt32 bufSize, remaining, count;
161 SSLRecord rec;
162
163 sslLogRecordIo("SSLRead top");
164 if((ctx == NULL) || (processed == NULL)) {
165 return paramErr;
166 }
167 bufSize = dataLength;
168 *processed = 0; /* Initialize in case we return with errSSLWouldBlock */
169
170 readRetry:
171 /* first handle cases in which we know we're finished */
172 switch(ctx->state) {
173 case SSL_HdskStateGracefulClose:
174 err = errSSLClosedGraceful;
175 goto abort;
176 case SSL_HdskStateErrorClose:
177 err = errSSLClosedAbort;
178 goto abort;
179 case SSL_HdskStateNoNotifyClose:
180 err = errSSLClosedNoNotify;
181 goto abort;
182 default:
183 break;
184 }
185
186 /* First, we have to wait until the session is ready to receive data,
187 so the encryption keys and such have been established. */
188 err = noErr;
189 while (ctx->readCipher.ready == 0) {
190 if ((err = SSLHandshakeProceed(ctx)) != 0) {
191 goto exit;
192 }
193 }
194
195 /* Attempt to service the write queue */
196 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
197 if (err != errSSLWouldBlock) {
198 goto exit;
199 }
200 err = noErr; /* Write blocking shouldn't stop attempts to read */
201 }
202
203 remaining = bufSize;
204 charPtr = (UInt8*)data;
205 if (ctx->receivedDataBuffer.data)
206 { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
207 if (count > bufSize)
208 count = bufSize;
209 memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count);
210 remaining -= count;
211 charPtr += count;
212 *processed += count;
213 ctx->receivedDataPos += count;
214 }
215
216 assert(ctx->receivedDataPos <= ctx->receivedDataBuffer.length);
217 assert(*processed + remaining == bufSize);
218 assert(charPtr == ((UInt8*)data) + *processed);
219
220 if (ctx->receivedDataBuffer.data != 0 &&
221 ctx->receivedDataPos >= ctx->receivedDataBuffer.length)
222 { SSLFreeBuffer(ctx->receivedDataBuffer, ctx);
223 ctx->receivedDataBuffer.data = 0;
224 ctx->receivedDataPos = 0;
225 }
226
227 /*
228 * This while statement causes a hang when using nonblocking low-level I/O!
229 while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
230 ..what we really have to do is just return as soon as we read one
231 record. A performance hit in the nonblocking case, but that is
232 the only way this code can work in both modes...
233 */
234 if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
235 { assert(ctx->receivedDataBuffer.data == 0);
236 if ((err = SSLReadRecord(rec, ctx)) != 0) {
237 goto exit;
238 }
239 if (rec.contentType == SSL_RecordTypeAppData ||
240 rec.contentType == SSL_RecordTypeV2_0)
241 { if (rec.contents.length <= remaining)
242 { memcpy(charPtr, rec.contents.data, rec.contents.length);
243 remaining -= rec.contents.length;
244 charPtr += rec.contents.length;
245 *processed += rec.contents.length;
246 /* COMPILER BUG!
247 * This:
248 * if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
249 * passes the address of rec to SSLFreeBuffer, not the address
250 * of the contents field (which should be offset 8 from the start
251 * of rec).
252 */
253 {
254 SSLBuffer *b = &rec.contents;
255 if ((err = SSLFreeBuffer(*b, ctx)) != 0) {
256 goto exit;
257 }
258 }
259 }
260 else
261 { memcpy(charPtr, rec.contents.data, remaining);
262 charPtr += remaining;
263 *processed += remaining;
264 ctx->receivedDataBuffer = rec.contents;
265 ctx->receivedDataPos = remaining;
266 remaining = 0;
267 }
268 }
269 else {
270 if ((err = SSLProcessProtocolMessage(rec, ctx)) != 0) {
271 goto exit;
272 }
273 if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0) {
274 goto exit;
275 }
276 }
277 }
278
279 err = noErr;
280
281 exit:
282 /* test for renegotiate: loop until something happens */
283 if((err == noErr) && (*processed == 0)) {
284 sslLogNegotiateDebug("SSLRead recursion");
285 goto readRetry;
286 }
287 /* shut down on serious errors */
288 switch(err) {
289 case noErr:
290 case errSSLWouldBlock:
291 case errSSLClosedGraceful:
292 case errSSLClosedNoNotify:
293 break;
294 default:
295 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
296 (int)err);
297 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
298 break;
299 }
300 abort:
301 sslIoTrace("SSLRead ", dataLength, *processed, err);
302 return err;
303 }
304
305 #if SSL_DEBUG
306 #include "appleCdsa.h"
307 #endif
308
309 OSStatus
310 SSLHandshake(SSLContext *ctx)
311 {
312 OSStatus err;
313
314 if(ctx == NULL) {
315 return paramErr;
316 }
317 if (ctx->state == SSL_HdskStateGracefulClose)
318 return errSSLClosedGraceful;
319 if (ctx->state == SSL_HdskStateErrorClose)
320 return errSSLClosedAbort;
321
322 if(ctx->validCipherSpecs == NULL) {
323 /* build list of legal cipherSpecs */
324 err = sslBuildCipherSpecArray(ctx);
325 if(err) {
326 return err;
327 }
328 }
329 err = noErr;
330 while (ctx->readCipher.ready == 0 || ctx->writeCipher.ready == 0)
331 { if ((err = SSLHandshakeProceed(ctx)) != 0)
332 return err;
333 }
334
335 /* one more flush at completion of successful handshake */
336 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
337 return err;
338 }
339 return noErr;
340 }
341
342
343 static OSStatus
344 SSLHandshakeProceed(SSLContext *ctx)
345 { OSStatus err;
346 SSLRecord rec;
347
348 if (ctx->state == SSL_HdskStateUninit)
349 if ((err = SSLInitConnection(ctx)) != 0)
350 return err;
351 if ((err = SSLServiceWriteQueue(ctx)) != 0)
352 return err;
353 assert(ctx->readCipher.ready == 0);
354 if ((err = SSLReadRecord(rec, ctx)) != 0)
355 return err;
356 if ((err = SSLProcessProtocolMessage(rec, ctx)) != 0)
357 { SSLFreeBuffer(rec.contents, ctx);
358 return err;
359 }
360 if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
361 return err;
362
363 return noErr;
364 }
365
366 static OSStatus
367 SSLInitConnection(SSLContext *ctx)
368 { OSStatus err = noErr;
369
370 if (ctx->protocolSide == SSL_ClientSide) {
371 SSLChangeHdskState(ctx, SSL_HdskStateClientUninit);
372 }
373 else
374 { assert(ctx->protocolSide == SSL_ServerSide);
375 SSLChangeHdskState(ctx, SSL_HdskStateServerUninit);
376 }
377
378 if (ctx->peerID.data != 0)
379 { SSLGetSessionData(&ctx->resumableSession, ctx);
380 /* Ignore errors; just treat as uncached session */
381 }
382
383 /*
384 * If we have a cached resumable session, blow it off if it's a version
385 * which is not currently enabled.
386 */
387 Boolean cachedV3OrTls1 = false;
388
389 if (ctx->resumableSession.data != 0) {
390
391 SSLProtocolVersion savedVersion;
392 Boolean enable;
393
394 if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession,
395 &savedVersion, ctx)) != 0) {
396 return err;
397 }
398 switch(savedVersion) {
399 case SSL_Version_2_0:
400 enable = ctx->versionSsl2Enable;
401 break;
402 case SSL_Version_3_0:
403 enable = ctx->versionSsl3Enable;
404 cachedV3OrTls1 = true; // avoid V2 hello
405 break;
406 case TLS_Version_1_0:
407 enable = ctx->versionTls1Enable;
408 cachedV3OrTls1 = true;
409 break;
410 default:
411 assert(0);
412 return errSSLInternal;
413 }
414 if(!enable) {
415 sslLogResumSessDebug("===Resumable session protocol mismatch");
416 SSLFreeBuffer(ctx->resumableSession, ctx);
417 cachedV3OrTls1 = false;
418 }
419 else {
420 sslLogResumSessDebug("===attempting to resume session");
421 }
422 }
423
424 /*
425 * If we're the client & handshake hasn't yet begun, start it by
426 * pretending we just received a hello request
427 */
428 if (ctx->state == SSL_HdskStateClientUninit && ctx->writeCipher.ready == 0)
429 {
430 assert(ctx->negProtocolVersion == SSL_Version_Undetermined);
431 if(ctx->versionSsl2Enable && !cachedV3OrTls1) {
432 /* SSL2 client hello with possible upgrade */
433 err = SSL2AdvanceHandshake(SSL2_MsgKickstart, ctx);
434 }
435 else {
436 err = SSLAdvanceHandshake(SSL_HdskHelloRequest, ctx);
437 }
438 }
439
440 return err;
441 }
442
443 static OSStatus
444 SSLServiceWriteQueue(SSLContext *ctx)
445 { OSStatus err = noErr, werr = noErr;
446 UInt32 written = 0;
447 SSLBuffer buf, recBuf;
448 WaitingRecord *rec;
449
450 while (!werr && ((rec = ctx->recordWriteQueue) != 0))
451 { buf.data = rec->data.data + rec->sent;
452 buf.length = rec->data.length - rec->sent;
453 werr = sslIoWrite(buf, &written, ctx);
454 rec->sent += written;
455 if (rec->sent >= rec->data.length)
456 { assert(rec->sent == rec->data.length);
457 assert(err == 0);
458 err = SSLFreeBuffer(rec->data, ctx);
459 assert(err == 0);
460 recBuf.data = (UInt8*)rec;
461 recBuf.length = sizeof(WaitingRecord);
462 ctx->recordWriteQueue = rec->next;
463 err = SSLFreeBuffer(recBuf, ctx);
464 assert(err == 0);
465 }
466 if (err)
467 return err;
468 }
469
470 return werr;
471 }
472
473 static OSStatus
474 SSLProcessProtocolMessage(SSLRecord &rec, SSLContext *ctx)
475 { OSStatus err;
476
477 switch (rec.contentType)
478 { case SSL_RecordTypeHandshake:
479 sslLogRxProtocolDebug("Handshake");
480 err = SSLProcessHandshakeRecord(rec, ctx);
481 break;
482 case SSL_RecordTypeAlert:
483 sslLogRxProtocolDebug("Alert");
484 err = SSLProcessAlert(rec, ctx);
485 break;
486 case SSL_RecordTypeChangeCipher:
487 sslLogRxProtocolDebug("ChangeCipher");
488 err = SSLProcessChangeCipherSpec(rec, ctx);
489 break;
490 case SSL_RecordTypeV2_0:
491 sslLogRxProtocolDebug("RecordTypeV2_0");
492 err = SSL2ProcessMessage(rec, ctx);
493 break;
494 default:
495 sslLogRxProtocolDebug("Bad msg");
496 return errSSLProtocol;
497 }
498
499 return err;
500 }
501
502 OSStatus
503 SSLClose(SSLContext *ctx)
504 {
505 OSStatus err = noErr;
506
507 sslHdskStateDebug("SSLClose");
508 if(ctx == NULL) {
509 return paramErr;
510 }
511 if (ctx->negProtocolVersion >= SSL_Version_3_0)
512 err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertCloseNotify, ctx);
513 if (err == 0)
514 err = SSLServiceWriteQueue(ctx);
515 SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose);
516 if (err == ioErr)
517 err = noErr; /* Ignore errors related to closed streams */
518 return err;
519 }
520
521 /*
522 * Determine how much data the client can be guaranteed to
523 * obtain via SSLRead() without blocking or causing any low-level
524 * read operations to occur.
525 *
526 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
527 * and receivedDataPos) are only used in this file.
528 */
529 OSStatus
530 SSLGetBufferedReadSize(SSLContextRef ctx,
531 size_t *bufSize) /* RETURNED */
532 {
533 if(ctx == NULL) {
534 return paramErr;
535 }
536 if(ctx->receivedDataBuffer.data == NULL) {
537 *bufSize = 0;
538 }
539 else {
540 assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
541 *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
542 }
543 return noErr;
544 }