1/* 2 * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * sslRecord.c - Encryption, decryption and MACing of data 26*/ 27 28#include <SecureTransport.h> 29#include "ssl.h" 30#include "sslRecord.h" 31#include "sslMemory.h" 32#include "sslContext.h" 33#include "sslAlertMessage.h" 34#include "sslDebug.h" 35#include "sslUtils.h" 36#include "sslDigests.h" 37#include "SSLRecordInternal.h" 38 39#include <string.h> 40#include <assert.h> 41 42#include <utilities/SecIOFormat.h> 43 44/* 45 * Lots of servers fail to provide closure alerts when they disconnect. 46 * For now we'll just accept it as long as it occurs on a clean record boundary 47 * (and the handshake is complete). 48 */ 49#define SSL_ALLOW_UNNOTICED_DISCONNECT 1 50 51 52static OSStatus errorTranslate(int recordErr) 53{ 54 switch(recordErr) { 55 case errSecSuccess: 56 return errSecSuccess; 57 case errSSLRecordInternal: 58 return errSSLInternal; 59 case errSSLRecordWouldBlock: 60 return errSSLWouldBlock; 61 case errSSLRecordProtocol: 62 return errSSLProtocol; 63 case errSSLRecordNegotiation: 64 return errSSLNegotiation; 65 case errSSLRecordClosedAbort: 66 return errSSLClosedAbort; 67 case errSSLRecordConnectionRefused: 68 return errSSLConnectionRefused; 69 case errSSLRecordDecryptionFail: 70 return errSSLDecryptionFail; 71 case errSSLRecordBadRecordMac: 72 return errSSLBadRecordMac; 73 case errSSLRecordRecordOverflow: 74 return errSSLRecordOverflow; 75 case errSSLRecordUnexpectedRecord: 76 return errSSLUnexpectedRecord; 77 default: 78 sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr); 79 return recordErr; 80 } 81} 82 83/* SSLWriteRecord 84 * Attempt to encrypt and queue an SSL record. 85 */ 86OSStatus 87SSLWriteRecord(SSLRecord rec, SSLContext *ctx) 88{ 89 OSStatus err; 90 91 err=errorTranslate(ctx->recFuncs->write(ctx->recCtx, rec)); 92 93 switch(err) { 94 case errSecSuccess: 95 break; 96 default: 97 sslErrorLog("unexpected error code returned in SSLWriteRecord: %d\n", (int)err); 98 break; 99 } 100 101 return err; 102} 103 104/* SSLFreeRecord 105 * Free a record returned by SSLReadRecord. 106 */ 107OSStatus 108SSLFreeRecord(SSLRecord rec, SSLContext *ctx) 109{ 110 return ctx->recFuncs->free(ctx->recCtx, rec); 111} 112 113/* SSLReadRecord 114 * Attempt to read & decrypt an SSL record. 115 * Record content should be freed using SSLFreeRecord 116 */ 117OSStatus 118SSLReadRecord(SSLRecord *rec, SSLContext *ctx) 119{ OSStatus err; 120 121 err=errorTranslate(ctx->recFuncs->read(ctx->recCtx, rec)); 122 123 switch(err) { 124 case errSecSuccess: 125 case errSSLWouldBlock: 126 break; 127 case errSSLUnexpectedRecord: 128 DTLSRetransmit(ctx); 129 break; 130 case errSSLDecryptionFail: 131 case errSSLBadRecordMac: 132 /* We never send a Decryption Failed alert, instead we send the BadRecordMac alert */ 133 /* This is TLS 1.1 compliant - Do it for all protocols versions. */ 134 /* Except for DTLS where we do not send any alert. */ 135 if(ctx->isDTLS) { 136 /* This will ensure we try to read again before returning to the caller 137 We do NOT want to use errSSLWouldBlock here, as this should only indicate 138 the IO read callback status */ 139 err=errSSLUnexpectedRecord; 140 } else { 141 SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx); 142 } 143 break; 144 case errSSLInternal: 145 SSLFatalSessionAlert(SSL_AlertInternalError, ctx); 146 break; 147 case errSSLRecordOverflow: 148 SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx); 149 break; 150 case errSSLClosedAbort: 151 case errSSLConnectionRefused: 152 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); 153 break; 154 default: 155 sslErrorLog("unknown error code returned in SSLReadRecord: %d\n", (int)err); 156 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); 157 break; 158 } 159 160 return err; 161} 162 163OSStatus SSLServiceWriteQueue(SSLContext *ctx) 164{ 165 return errorTranslate(ctx->recFuncs->serviceWriteQueue(ctx->recCtx)); 166} 167