1/*
2 * Copyright (c) 2002,2005-2007,2010-2011 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 * ssl3RecordCallouts.c - SSLv3-specific routines for SslTlsCallouts.
26 */
27
28/* THIS FILE CONTAINS KERNEL CODE */
29
30#include <AssertMacros.h>
31#include <string.h>
32#include <stdint.h>
33#include <inttypes.h>
34
35#ifdef KERNEL
36#include <sys/types.h>
37#else
38#include <stddef.h>
39#endif
40
41#include "sslDebug.h"
42#include "sslMemory.h"
43#include "sslUtils.h"
44#include "sslRand.h"
45
46#include "tls_record.h"
47
48
49/*
50 * ssl3WriteRecord does not send alerts on failure, out of the assumption/fear
51 * that this might result in a loop (since sending an alert causes ssl3WriteRecord
52 * to be called).
53 *
54 * As far as I can tell, we can use this same routine for SSLv3 and TLSv1, as long
55 * as we're not trying to use the "variable length padding" feature of TLSv1.
56 * OpenSSL doesn't use that feature; for now, neither will we. Thus this routine
57 * is used for the SslTlsCallouts.writeRecord function for both protocols.
58 */
59int ssl3WriteRecord(
60	SSLRecord rec,
61	struct SSLRecordInternalContext *ctx)
62{
63	int        err;
64    int             padding = 0, i;
65    WaitingRecord   *out = NULL, *queue;
66    SSLBuffer       payload, mac;
67    uint8_t           *charPtr;
68    uint16_t          payloadSize,blockSize = 0;
69    int             head = 5;
70
71	switch(rec.protocolVersion) {
72        case DTLS_Version_1_0:
73            head += 8;
74		case SSL_Version_3_0:
75		case TLS_Version_1_0:
76        case TLS_Version_1_1:
77        case TLS_Version_1_2:
78			break;
79		default:
80			check(0);
81			return errSSLRecordInternal;
82	}
83    check(rec.contents.length <= 16384);
84
85    sslLogRecordIo("type = %02x, ver = %04x, len = %ld, seq = %016llx",
86                   rec.contentType, rec.protocolVersion, rec.contents.length,
87                   ctx->writeCipher.sequenceNum);
88
89    /* Allocate enough room for the transmitted record, which will be:
90     *  5 bytes of header (13 for DTLS) +
91     *  IV [block cipher and TLS1.1 or DTLS 1.0 only]
92     *  encrypted contents +
93     *  macLength +
94     *  padding [block ciphers only] +
95     *  padding length field (1 byte) [block ciphers only]
96     */
97    payloadSize = (uint16_t) rec.contents.length;
98    CipherType cipherType = ctx->writeCipher.symCipher->params->cipherType;
99    const Cipher *cipher = &ctx->writeCipher.symCipher->c.cipher;
100    const AEADCipher *aead = &ctx->writeCipher.symCipher->c.aead;
101    blockSize = ctx->writeCipher.symCipher->params->blockSize;
102    switch (cipherType) {
103        case blockCipherType:
104            payloadSize += ctx->writeCipher.macRef->hash->digestSize;
105            padding = blockSize - (payloadSize % blockSize) - 1;
106            payloadSize += padding + 1;
107            /* TLS 1.1, TLS1.2 and DTLS 1.0 have an extra block for IV */
108            if(ctx->negProtocolVersion >= TLS_Version_1_1) {
109                payloadSize += blockSize;
110            }
111            break;
112        case streamCipherType:
113            payloadSize += ctx->writeCipher.macRef->hash->digestSize;
114            break;
115        case aeadCipherType:
116            /* AES_GCM doesn't need padding. */
117            payloadSize += aead->macSize;
118            break;
119        default:
120            check(0);
121			return errSSLRecordInternal;
122    }
123
124	out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) +
125		head + payloadSize);
126	out->next = NULL;
127	out->sent = 0;
128	out->length = head + payloadSize;
129
130    charPtr = out->data;
131    *(charPtr++) = rec.contentType;
132    charPtr = SSLEncodeInt(charPtr, rec.protocolVersion, 2);
133
134    /* DTLS sequence number */
135    if(rec.protocolVersion == DTLS_Version_1_0)
136        charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum);
137
138    charPtr = SSLEncodeInt(charPtr, payloadSize, 2);
139
140    /* Also for DTLS */
141    if((ctx->negProtocolVersion >= TLS_Version_1_1) &&
142       (cipherType == blockCipherType))
143    {
144        SSLBuffer randomIV;
145        randomIV.data = charPtr;
146        randomIV.length = blockSize;
147        if((err = sslRand(&randomIV)) != 0)
148            return err;
149        charPtr += blockSize;
150    }
151    if (cipherType == aeadCipherType) {
152        /* Encode the explicit iv, for AES_GCM we just use the 8 byte
153           sequenceNum as the explicitIV.
154           Ideally this needs to be done in the algorithm itself, by an
155           extra function pointer in AEADCipher.  */
156        charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum);
157        /* TODO: If we ever add any mode other than GCM this code might have
158           to be different. */
159        /* TODO: Pass 4 byte implicit and 8 byte explicit IV to cipher */
160        //err = ctx->writeCipher.symCipher->c.aead.setIV(charPtr, &ctx->writeCipher, ctx);
161    }
162
163    /* Copy the contents into the output buffer */
164    memcpy(charPtr, rec.contents.data, rec.contents.length);
165    payload.data = charPtr;
166    payload.length = rec.contents.length;
167
168    charPtr += rec.contents.length;
169
170    /* MAC the data */
171    if (cipherType != aeadCipherType) {
172        /* MAC immediately follows data */
173        mac.data = charPtr;
174        mac.length = ctx->writeCipher.macRef->hash->digestSize;
175        charPtr += mac.length;
176        if (mac.length > 0)     /* Optimize away null case */
177        {
178            check(ctx->sslTslCalls != NULL);
179            if ((err = ctx->sslTslCalls->computeMac(rec.contentType,
180                    payload,
181                    mac,
182                    &ctx->writeCipher,
183                    ctx->writeCipher.sequenceNum,
184                    ctx)) != 0)
185                goto fail;
186        }
187    }
188
189    /* For TLS 1.1 and DTLS, we would need to specifiy the IV, but instead
190     we are clever like this: since the IV is just one block in front,
191     we encrypt it with the rest of the data. The actual transmitted IV
192     is the result of the encryption, with whatever internal IV is used.
193     This method is explained in the TLS 1.1 RFC */
194    if(ctx->negProtocolVersion >= TLS_Version_1_1 &&
195       cipherType == blockCipherType)
196    {
197            payload.data -= blockSize;
198    }
199
200    /* Update payload to reflect encrypted data: IV, contents, mac & padding */
201    payload.length = payloadSize;
202
203
204    switch (cipherType) {
205        case blockCipherType:
206            /* Fill in the padding bytes & padding length field with the
207             * padding value; the protocol only requires the last byte,
208             * but filling them all in avoids leaking data */
209            for (i = 1; i <= padding + 1; ++i)
210                payload.data[payload.length - i] = padding;
211            /* DROPTRHOUGH */
212        case streamCipherType:
213            /* Encrypt the data */
214            if ((err = cipher->encrypt(payload.data,
215                payload.data, payload.length, ctx->writeCipher.cipherCtx)) != 0)
216                goto fail;
217            break;
218        case aeadCipherType:
219            check(0);
220            break;
221        default:
222            check(0);
223			return errSSLRecordInternal;
224    }
225
226    /* Enqueue the record to be written from the idle loop */
227    if (ctx->recordWriteQueue == 0)
228        ctx->recordWriteQueue = out;
229    else
230    {   queue = ctx->recordWriteQueue;
231        while (queue->next != 0)
232            queue = queue->next;
233        queue->next = out;
234    }
235
236    /* Increment the sequence number */
237    IncrementUInt64(&ctx->writeCipher.sequenceNum);
238
239    return 0;
240
241fail:
242	/*
243	 * Only for if we fail between when the WaitingRecord is allocated and when
244	 * it is queued
245	 */
246	sslFree(out);
247    return err;
248}
249
250static int ssl3DecryptRecord(
251	uint8_t type,
252	SSLBuffer *payload,
253	struct SSLRecordInternalContext *ctx)
254{
255	int    err;
256    SSLBuffer   content;
257
258    CipherType cipherType = ctx->readCipher.symCipher->params->cipherType;
259    const Cipher *c = &ctx->readCipher.symCipher->c.cipher;
260    switch (cipherType) {
261        case blockCipherType:
262            if ((payload->length % ctx->readCipher.symCipher->params->blockSize) != 0)
263            {
264                return errSSLRecordDecryptionFail;
265            }
266            /* DROPTHROUGH */
267        case streamCipherType:
268            /* Decrypt in place */
269            err = c->decrypt(payload->data, payload->data,
270                             payload->length, ctx->readCipher.cipherCtx);
271            break;
272        case aeadCipherType:
273        default:
274            check(0);
275			return errSSLRecordInternal;
276    }
277    if (err != 0)
278    {
279        return errSSLRecordDecryptionFail;
280    }
281
282	/* Locate content within decrypted payload */
283    content.data = payload->data;
284    content.length = payload->length - ctx->readCipher.macRef->hash->digestSize;
285    if (cipherType == blockCipherType)
286    {   /* padding can't be equal to or more than a block */
287        if (payload->data[payload->length - 1] >= ctx->readCipher.symCipher->params->blockSize)
288        {
289		sslErrorLog("DecryptSSLRecord: bad padding length (%d)\n",
290			(unsigned)payload->data[payload->length - 1]);
291            return errSSLRecordDecryptionFail;
292        }
293        content.length -= 1 + payload->data[payload->length - 1];
294						/* Remove block size padding */
295    }
296
297	/* Verify MAC on payload */
298    if (ctx->readCipher.macRef->hash->digestSize > 0)
299		/* Optimize away MAC for null case */
300        if ((err = SSLVerifyMac(type, &content,
301				payload->data + content.length, ctx)) != 0)
302        {
303            return errSSLRecordBadRecordMac;
304        }
305
306    *payload = content;     /* Modify payload buffer to indicate content length */
307
308    return 0;
309}
310
311/* initialize a per-CipherContext HashHmacContext for use in MACing each record */
312static int ssl3InitMac (
313	CipherContext *cipherCtx)		// macRef, macSecret valid on entry
314									// macCtx valid on return
315{
316	const HashReference *hash;
317	SSLBuffer *hashCtx;
318	int serr;
319
320	check(cipherCtx->macRef != NULL);
321	hash = cipherCtx->macRef->hash;
322	check(hash != NULL);
323
324	hashCtx = &cipherCtx->macCtx.hashCtx;
325	if(hashCtx->data != NULL) {
326		SSLFreeBuffer(hashCtx);
327	}
328	serr = SSLAllocBuffer(hashCtx, hash->contextSize);
329	if(serr) {
330		return serr;
331	}
332	return 0;
333}
334
335static int ssl3FreeMac (
336	CipherContext *cipherCtx)
337{
338	SSLBuffer *hashCtx;
339
340	check(cipherCtx != NULL);
341	/* this can be called on a completely zeroed out CipherContext... */
342	if(cipherCtx->macRef == NULL) {
343		return 0;
344	}
345	hashCtx = &cipherCtx->macCtx.hashCtx;
346	if(hashCtx->data != NULL) {
347		sslFree(hashCtx->data);
348		hashCtx->data = NULL;
349	}
350	hashCtx->length = 0;
351	return 0;
352}
353
354static int ssl3ComputeMac (
355	uint8_t type,
356	SSLBuffer data,
357	SSLBuffer mac, 					// caller mallocs data
358	CipherContext *cipherCtx,		// assumes macCtx, macRef
359	sslUint64 seqNo,
360	struct SSLRecordInternalContext *ctx)
361{
362	int        err;
363    uint8_t           innerDigestData[SSL_MAX_DIGEST_LEN];
364    uint8_t           scratchData[11], *charPtr;
365    SSLBuffer       digest, digestCtx, scratch;
366	SSLBuffer		secret;
367
368    const HashReference	*hash;
369
370	check(cipherCtx != NULL);
371	check(cipherCtx->macRef != NULL);
372	hash = cipherCtx->macRef->hash;
373	check(hash != NULL);
374    check(hash->macPadSize <= MAX_MAC_PADDING);
375    check(hash->digestSize <= SSL_MAX_DIGEST_LEN);
376	digestCtx = cipherCtx->macCtx.hashCtx;		// may be NULL, for null cipher
377	secret.data = cipherCtx->macSecret;
378	secret.length = hash->digestSize;
379
380	/* init'd early in SSLNewContext() */
381    check(SSLMACPad1[0] == 0x36 && SSLMACPad2[0] == 0x5C);
382
383	/*
384	 * MAC = hash( MAC_write_secret + pad_2 +
385	 *		       hash( MAC_write_secret + pad_1 + seq_num + type +
386	 *			         length + content )
387	 *			 )
388	 */
389    if ((err = hash->init(&digestCtx)) != 0)
390        goto exit;
391    if ((err = hash->update(&digestCtx, &secret)) != 0)    /* MAC secret */
392        goto exit;
393    scratch.data = (uint8_t *)SSLMACPad1;
394    scratch.length = hash->macPadSize;
395    if ((err = hash->update(&digestCtx, &scratch)) != 0)   /* pad1 */
396        goto exit;
397    charPtr = scratchData;
398    charPtr = SSLEncodeUInt64(charPtr, seqNo);
399    *charPtr++ = type;
400    charPtr = SSLEncodeSize(charPtr, data.length, 2);
401    scratch.data = scratchData;
402    scratch.length = 11;
403    check(charPtr = scratchData+11);
404    if ((err = hash->update(&digestCtx, &scratch)) != 0)
405										/* sequenceNo, type & length */
406        goto exit;
407    if ((err = hash->update(&digestCtx, &data)) != 0)      /* content */
408        goto exit;
409    digest.data = innerDigestData;
410    digest.length = hash->digestSize;
411    if ((err = hash->final(&digestCtx, &digest)) != 0) 	/* figure inner digest */
412        goto exit;
413
414    if ((err = hash->init(&digestCtx)) != 0)
415        goto exit;
416    if ((err = hash->update(&digestCtx, &secret)) != 0)    /* MAC secret */
417        goto exit;
418    scratch.data = (uint8_t *)SSLMACPad2;
419    scratch.length = hash->macPadSize;
420    if ((err = hash->update(&digestCtx, &scratch)) != 0)   /* pad2 */
421        goto exit;
422    if ((err = hash->update(&digestCtx, &digest)) != 0)    /* inner digest */
423        goto exit;
424    if ((err = hash->final(&digestCtx, &mac)) != 0)   	 /* figure the mac */
425        goto exit;
426
427    err = 0; /* redundant, I know */
428
429exit:
430    return err;
431}
432
433
434const SslRecordCallouts Ssl3RecordCallouts = {
435	ssl3DecryptRecord,
436	ssl3WriteRecord,
437	ssl3InitMac,
438	ssl3FreeMac,
439	ssl3ComputeMac,
440};
441