/ lib / sslHandshakeFinish.c
sslHandshakeFinish.c
  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 "tls_handshake_priv.h"
 30  
 31  #include "sslHandshake.h"
 32  #include "sslHandshake_priv.h"
 33  #include "sslMemory.h"
 34  #include "sslDebug.h"
 35  #include "sslUtils.h"
 36  #include "sslDigests.h"
 37  
 38  #include <string.h>
 39  #include <assert.h>
 40  
 41  /* Define the following to 1 if you want http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04,
 42   otherwise you get http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-03 */
 43  #define NPN_MSG_HAS_EXT_TYPE 0
 44  
 45  int
 46  SSLEncodeNPNEncryptedExtensionMessage(tls_buffer *npn, tls_handshake_t ctx)
 47  {
 48      OSStatus        err;
 49      unsigned        msgSize;
 50      unsigned        extnSize;
 51      unsigned        paddingSize;
 52      UInt8           *p;
 53      int             head;
 54  
 55      if(ctx->npnOwnData.data == NULL)
 56          return errSSLBadConfiguration;
 57      assert(ctx->npnOwnData.length < 256);
 58  
 59      /* Total Size = Header (handshake message type) + Extension Data (Selected Protocol + Padding) */
 60      paddingSize = 32 - ((ctx->npnOwnData.length + 2) % 32);
 61      /* The selected protocol and padding opaque byte strings each start with a 1-byte length */
 62      extnSize = 1 + (unsigned)ctx->npnOwnData.length + 1 + paddingSize;
 63  
 64      msgSize = extnSize;
 65  #if NPN_MSG_HAS_EXT_TYPE
 66      msgSize += 4;
 67  #endif
 68  
 69      head = SSLHandshakeHeaderSize(ctx);
 70      if ((err = SSLAllocBuffer(npn, msgSize + head)) != 0) {
 71          return err;
 72      }
 73  
 74      /* Populate the record with the header */
 75      p = SSLEncodeHandshakeHeader(ctx, npn, SSL_HdskNPNEncryptedExtension, msgSize);
 76  
 77  #if NPN_MSG_HAS_EXT_TYPE
 78      /* Latest draft require this - google does not actually accept this */
 79      /* Extension type */
 80      p = SSLEncodeInt(p, SSL_HE_NPN, 2);
 81  
 82      /* Extension data len */
 83      p = SSLEncodeInt(p, extnSize, 2);
 84  #endif
 85  
 86      /* Now include the length of the selected protocol */
 87      p = SSLEncodeInt(p, ctx->npnOwnData.length, 1);
 88  
 89      /* Fill the record with the selected protocol */
 90      memcpy(p, ctx->npnOwnData.data, ctx->npnOwnData.length);
 91      p += ctx->npnOwnData.length;
 92  
 93      /* Now include the length of the padding */
 94      p = SSLEncodeInt(p, paddingSize, 1);
 95  
 96      /* Finish the record with the padding */
 97  	memset(p, 0, paddingSize);
 98  
 99      ctx->npn_confirmed = true;
100  
101      return errSSLSuccess;
102  }
103  
104  static int
105  SSLProcessEncryptedNPNExtension(const uint8_t *p, size_t extLen, tls_handshake_t ctx)
106  {
107      int err;
108      if (!ctx->npn_announced)
109          return errSSLProtocol;
110  
111      ctx->npn_received = true;
112      if ((err = SSLAllocBuffer(&ctx->npnPeerData, extLen)) != 0)
113          return err;
114      memcpy(ctx->npnPeerData.data, p, ctx->npnPeerData.length);
115      return 0;
116  }
117  
118  int
119  SSLProcessEncryptedExtension(tls_buffer message, tls_handshake_t ctx)
120  {
121      const uint8_t *p = message.data;
122  
123  #if NPN_MSG_HAS_EXT_TYPE
124      int err;
125      while (message.length) {
126          unsigned int extName, extLen;
127  
128          if (message.length < 4)
129              return errSSLProtocol;
130  
131          extName = SSLDecodeInt(p, 2);
132          p += 2;
133          extLen = SSLDecodeInt(p, 2);
134          p += 2;
135  
136          message.length -= 4;
137  
138          if (message.length < extLen)
139              return errSSLProtocol;
140  
141          switch (extName) {
142              case SSL_HE_NPN:
143                  if((err = SSLProcessEncryptedNPNExtension(p, extLen, ctx)))
144                      return err;
145                  p += extLen;
146                  break;
147              default:
148                  p += extLen;
149                  break;
150          }
151          message.length -= extLen;
152      }
153      return errSSLSuccess;
154  #else
155      return SSLProcessEncryptedNPNExtension(p, message.length, ctx);
156  #endif
157  }
158  
159  int
160  SSLEncodeFinishedMessage(tls_buffer *finished,  tls_handshake_t ctx)
161  {
162      int        err;
163      tls_buffer       finishedMsg;
164      unsigned		finishedSize;
165  	UInt8           *p;
166      int             head;
167  
168  	/* size and version depend on negotiatedProtocol */
169  	switch(ctx->negProtocolVersion) {
170  		case tls_protocol_version_SSL_3:
171  			finishedSize = 36;
172  			break;
173          case tls_protocol_version_DTLS_1_0:
174  		case tls_protocol_version_TLS_1_0:
175          case tls_protocol_version_TLS_1_1:
176          case tls_protocol_version_TLS_1_2: /* TODO: Support variable finishedSize. */
177  			finishedSize = 12;
178  			break;
179  		default:
180  			assert(0);
181  			return errSSLInternal;
182  	}
183  	/* msg = type + 3 bytes len + finishedSize */
184      head = SSLHandshakeHeaderSize(ctx);
185      if ((err = SSLAllocBuffer(finished, finishedSize + head)) != 0)
186          return err;
187  
188      p = SSLEncodeHandshakeHeader(ctx, finished, SSL_HdskFinished, finishedSize);
189  
190      finishedMsg.data = p;
191      finishedMsg.length = finishedSize;
192  
193      err = ctx->sslTslCalls->computeFinishedMac(ctx, finishedMsg, ctx->isServer);
194  
195      if(err)
196          return err;
197  
198      /* Keep this around for secure renegotiation */
199      SSLFreeBuffer(&ctx->ownVerifyData);
200      return SSLCopyBuffer(&finishedMsg, &ctx->ownVerifyData);
201  }
202  
203  int
204  SSLProcessFinished(tls_buffer message, tls_handshake_t ctx)
205  {   int        err;
206      tls_buffer       expectedFinished;
207      unsigned		finishedSize;
208  
209  	switch(ctx->negProtocolVersion) {
210  		case tls_protocol_version_SSL_3:
211  			finishedSize = 36;
212  			break;
213  		case tls_protocol_version_DTLS_1_0:
214  		case tls_protocol_version_TLS_1_0:
215          case tls_protocol_version_TLS_1_1:
216          case tls_protocol_version_TLS_1_2: /* TODO: Support variable finishedSize. */
217  			finishedSize = 12;
218  			break;
219  		default:
220  			assert(0);
221  			return errSSLInternal;
222  	}
223      if (message.length != finishedSize) {
224  		sslErrorLog("SSLProcessFinished: msg len error 1\n");
225          return errSSLProtocol;
226      }
227      expectedFinished.data = 0;
228      if ((err = SSLAllocBuffer(&expectedFinished, finishedSize)))
229          return err;
230      if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, expectedFinished, !ctx->isServer)) != 0)
231          goto fail;
232  
233      if (memcmp(expectedFinished.data, message.data, finishedSize) != 0)
234      {
235     		sslErrorLog("SSLProcessFinished: memcmp failure\n");
236     	 	err = errSSLProtocol;
237          goto fail;
238      }
239  
240      /* Keep this around for secure renegotiation */
241      SSLFreeBuffer(&ctx->peerVerifyData);
242      err = SSLCopyBuffer(&expectedFinished, &ctx->peerVerifyData);
243  
244  fail:
245      SSLFreeBuffer(&expectedFinished);
246      return err;
247  }
248  
249  int
250  SSLEncodeServerHelloDone(tls_buffer *helloDone, tls_handshake_t ctx)
251  {   int          err;
252      int               head;
253  
254  	assert(ctx->negProtocolVersion >= tls_protocol_version_SSL_3);
255      head = SSLHandshakeHeaderSize(ctx);
256      if ((err = SSLAllocBuffer(helloDone, head)))
257          return err;
258  
259      SSLEncodeHandshakeHeader(ctx, helloDone, SSL_HdskServerHelloDone, 0); /* Message has 0 length */
260  
261      return errSSLSuccess;
262  }
263  
264  int
265  SSLProcessServerHelloDone(tls_buffer message, tls_handshake_t ctx)
266  {
267      assert(!ctx->isServer);
268      if (message.length != 0) {
269      	sslErrorLog("SSLProcessServerHelloDone: nonzero msg len\n");
270          return errSSLProtocol;
271      }
272      return errSSLSuccess;
273  }