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 * sslHandshakeFinish.c - Finished and server hello done messages.
26 */
27
28#include "sslContext.h"
29#include "sslHandshake.h"
30#include "sslMemory.h"
31#include "sslDebug.h"
32#include "sslUtils.h"
33#include "sslDigests.h"
34
35#include <string.h>
36#include <assert.h>
37
38OSStatus
39SSLEncodeFinishedMessage(SSLRecord *finished, SSLContext *ctx)
40{   OSStatus        err;
41    SSLBuffer       finishedMsg;
42    Boolean         isServerMsg;
43    unsigned		finishedSize;
44	UInt8           *p;
45    int             head;
46
47	/* size and version depend on negotiatedProtocol */
48	switch(ctx->negProtocolVersion) {
49		case SSL_Version_3_0:
50			finishedSize = 36;
51			break;
52        case DTLS_Version_1_0:
53		case TLS_Version_1_0:
54        case TLS_Version_1_1:
55        case TLS_Version_1_2: /* TODO: Support variable finishedSize. */
56			finishedSize = 12;
57			break;
58		default:
59			assert(0);
60			return errSSLInternal;
61	}
62    finished->protocolVersion = ctx->negProtocolVersion;
63
64    finished->contentType = SSL_RecordTypeHandshake;
65	/* msg = type + 3 bytes len + finishedSize */
66    head = SSLHandshakeHeaderSize(finished);
67    if ((err = SSLAllocBuffer(&finished->contents, finishedSize + head)) != 0)
68        return err;
69
70    p = SSLEncodeHandshakeHeader(ctx, finished, SSL_HdskFinished, finishedSize);
71
72    finishedMsg.data = p;
73    finishedMsg.length = finishedSize;
74
75    isServerMsg = (ctx->protocolSide == kSSLServerSide) ? true : false;
76    err = ctx->sslTslCalls->computeFinishedMac(ctx, finishedMsg, isServerMsg);
77
78    if(err)
79        return err;
80
81    /* Keep this around for secure renegotiation */
82    SSLFreeBuffer(&ctx->ownVerifyData);
83    return SSLCopyBuffer(&finishedMsg, &ctx->ownVerifyData);
84}
85
86OSStatus
87SSLProcessFinished(SSLBuffer message, SSLContext *ctx)
88{   OSStatus        err;
89    SSLBuffer       expectedFinished;
90    Boolean         isServerMsg;
91    unsigned		finishedSize;
92
93	switch(ctx->negProtocolVersion) {
94		case SSL_Version_3_0:
95			finishedSize = 36;
96			break;
97		case DTLS_Version_1_0:
98		case TLS_Version_1_0:
99        case TLS_Version_1_1:
100        case TLS_Version_1_2: /* TODO: Support variable finishedSize. */
101			finishedSize = 12;
102			break;
103		default:
104			assert(0);
105			return errSSLInternal;
106	}
107    if (message.length != finishedSize) {
108		sslErrorLog("SSLProcessFinished: msg len error 1\n");
109        return errSSLProtocol;
110    }
111    expectedFinished.data = 0;
112    if ((err = SSLAllocBuffer(&expectedFinished, finishedSize)))
113        return err;
114    isServerMsg = (ctx->protocolSide == kSSLServerSide) ? false : true;
115    if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, expectedFinished, isServerMsg)) != 0)
116        goto fail;
117
118    if (memcmp(expectedFinished.data, message.data, finishedSize) != 0)
119    {
120   		sslErrorLog("SSLProcessFinished: memcmp failure\n");
121   	 	err = errSSLProtocol;
122        goto fail;
123    }
124
125    /* Keep this around for secure renegotiation */
126    SSLFreeBuffer(&ctx->peerVerifyData);
127    err = SSLCopyBuffer(&expectedFinished, &ctx->peerVerifyData);
128
129fail:
130    SSLFreeBuffer(&expectedFinished);
131    return err;
132}
133
134OSStatus
135SSLEncodeServerHelloDone(SSLRecord *helloDone, SSLContext *ctx)
136{   OSStatus          err;
137    int               head;
138
139    helloDone->contentType = SSL_RecordTypeHandshake;
140	assert(ctx->negProtocolVersion >= SSL_Version_3_0);
141    helloDone->protocolVersion = ctx->negProtocolVersion;
142    head = SSLHandshakeHeaderSize(helloDone);
143    if ((err = SSLAllocBuffer(&helloDone->contents, head)))
144        return err;
145
146    SSLEncodeHandshakeHeader(ctx, helloDone, SSL_HdskServerHelloDone, 0); /* Message has 0 length */
147
148    return errSecSuccess;
149}
150
151OSStatus
152SSLProcessServerHelloDone(SSLBuffer message, SSLContext *ctx)
153{   assert(ctx->protocolSide == kSSLClientSide);
154    if (message.length != 0) {
155    	sslErrorLog("SSLProcessServerHelloDone: nonzero msg len\n");
156        return errSSLProtocol;
157    }
158    return errSecSuccess;
159}
160