1/*
2 * Copyright (c) 1999-2001,2005-2007,2010-2014 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{
120    return errorTranslate(ctx->recFuncs->read(ctx->recCtx, rec));
121}
122
123OSStatus SSLServiceWriteQueue(SSLContext *ctx)
124{
125    return errorTranslate(ctx->recFuncs->serviceWriteQueue(ctx->recCtx));
126}
127