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 }