sslChangeCipher.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 * sslChangeCipher.c - support for change cipher spec messages 26 */ 27 28 #include "tls_handshake_priv.h" 29 #include "sslHandshake.h" 30 #include "sslHandshake_priv.h" 31 #include "sslMemory.h" 32 #include "sslAlertMessage.h" 33 #include "sslDebug.h" 34 #include "sslCipherSpecs.h" 35 36 #include <assert.h> 37 #include <string.h> 38 39 int 40 SSLEncodeChangeCipherSpec(tls_buffer *rec, tls_handshake_t ctx) 41 { int err; 42 43 assert(ctx->writePending_ready); 44 45 sslLogNegotiateDebug("===Sending changeCipherSpec msg"); 46 assert(ctx->negProtocolVersion >= tls_protocol_version_SSL_3); 47 rec->length = 1; 48 if ((err = SSLAllocBuffer(rec, 1))) 49 return err; 50 rec->data[0] = 1; 51 52 ctx->messageQueueContainsChangeCipherSpec=true; 53 54 return errSSLSuccess; 55 } 56 57 int 58 SSLProcessChangeCipherSpec(tls_buffer rec, tls_handshake_t ctx) 59 { int err; 60 61 if (rec.length != 1 || rec.data[0] != 1) 62 { 63 #warning This is fishy: 64 if(ctx->isDTLS) 65 return errSSLUnexpectedRecord; 66 67 SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); 68 sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n", 69 (unsigned)rec.length, (unsigned)rec.data[0]); 70 return errSSLProtocol; 71 } 72 73 /* 74 * Handle PAC-style session resumption, client side only. 75 * In that case, the handshake state was left in either KeyExchange or 76 * Cert. 77 * Other client side resumption cases are handled in SSLAdvanceHandshake 78 * (case SSL_HdskServerHello:). 79 */ 80 if((!ctx->isServer) && 81 (ctx->externalSessionTicket.length != 0) && 82 ((ctx->state == SSL_HdskStateKeyExchange) || (ctx->state == SSL_HdskStateCert)) && 83 (ctx->masterSecretCallback != NULL)) { 84 size_t secretLen = SSL_MASTER_SECRET_SIZE; 85 sslEapDebug("Client side resuming based on masterSecretCallback"); 86 ctx->masterSecretCallback(ctx->masterSecretArg, 87 ctx->masterSecret, &secretLen); 88 ctx->sessionMatch = 1; 89 90 /* set up selectedCipherSpec */ 91 if ((err = ValidateSelectedCiphersuite(ctx)) != 0) { 92 return err; 93 } 94 if((err = SSLInitPendingCiphers(ctx)) != 0) { 95 SSLFatalSessionAlert(SSL_AlertInternalError, ctx); 96 return err; 97 } 98 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); 99 } 100 101 if (!ctx->readPending_ready || ctx->state != SSL_HdskStateChangeCipherSpec) 102 { 103 // This mean we received a ChangeCipherSpec message when we didnt expect it. 104 // Just drop silently. 105 if(ctx->isDTLS) 106 return errSSLUnexpectedRecord; 107 108 SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); 109 sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n", 110 (unsigned)ctx->readPending_ready, (unsigned)ctx->state); 111 return errSSLProtocol; 112 } 113 114 sslLogNegotiateDebug("===Processing changeCipherSpec msg"); 115 116 /* Install new cipher spec on read side */ 117 /* TODO: if we want to enable app data during most of handshake, 118 we should disable read channel here: 119 sslReadReady(ctx, false); 120 */ 121 if ((err = ctx->callbacks->advance_read_cipher(ctx->callback_ctx)) != 0) 122 { 123 SSLFatalSessionAlert(SSL_AlertInternalError, ctx); 124 return err; 125 } 126 /* make the pending read cipher invalid */ 127 ctx->readPending_ready = 0; 128 SSLChangeHdskState(ctx, SSL_HdskStateFinished); 129 return errSSLSuccess; 130 } 131