2 * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * sslChangeCipher.c - support for change cipher spec messages
28 #include "sslContext.h"
29 #include "sslHandshake.h"
30 #include "sslMemory.h"
31 #include "sslAlertMessage.h"
33 #include "sslCipherSpecs.h"
39 SSLEncodeChangeCipherSpec(SSLRecord
*rec
, SSLContext
*ctx
)
42 assert(ctx
->writePending_ready
);
44 sslLogNegotiateDebug("===Sending changeCipherSpec msg");
45 rec
->contentType
= SSL_RecordTypeChangeCipher
;
46 assert(ctx
->negProtocolVersion
>= SSL_Version_3_0
);
47 rec
->protocolVersion
= ctx
->negProtocolVersion
;
48 rec
->contents
.length
= 1;
49 if ((err
= SSLAllocBuffer(&rec
->contents
, 1)))
51 rec
->contents
.data
[0] = 1;
53 ctx
->messageQueueContainsChangeCipherSpec
=true;
59 SSLProcessChangeCipherSpec(SSLRecord rec
, SSLContext
*ctx
)
62 if (rec
.contents
.length
!= 1 || rec
.contents
.data
[0] != 1)
65 return errSSLWouldBlock
;
67 SSLFatalSessionAlert(SSL_AlertUnexpectedMsg
, ctx
);
68 sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n",
69 (unsigned)rec
.contents
.length
, (unsigned)rec
.contents
.data
[0]);
70 return errSSLProtocol
;
74 * Handle PAC-style session resumption, client side only.
75 * In that case, the handshake state was left in either KeyExchange or
78 if((ctx
->protocolSide
== kSSLClientSide
) &&
79 (ctx
->sessionTicket
.length
!= 0) &&
80 ((ctx
->state
== SSL_HdskStateKeyExchange
) || (ctx
->state
== SSL_HdskStateCert
)) &&
81 (ctx
->masterSecretCallback
!= NULL
)) {
82 size_t secretLen
= SSL_MASTER_SECRET_SIZE
;
83 sslEapDebug("Client side resuming based on masterSecretCallback");
84 ctx
->masterSecretCallback(ctx
, ctx
->masterSecretArg
,
85 ctx
->masterSecret
, &secretLen
);
86 ctx
->sessionMatch
= 1;
88 /* set up selectedCipherSpec */
89 if ((err
= FindCipherSpec(ctx
)) != 0) {
92 if((err
= SSLInitPendingCiphers(ctx
)) != 0) {
93 SSLFatalSessionAlert(SSL_AlertInternalError
, ctx
);
96 SSLChangeHdskState(ctx
, SSL_HdskStateChangeCipherSpec
);
99 if (!ctx
->readPending_ready
|| ctx
->state
!= SSL_HdskStateChangeCipherSpec
)
102 return errSSLWouldBlock
;
104 SSLFatalSessionAlert(SSL_AlertUnexpectedMsg
, ctx
);
105 sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n",
106 (unsigned)ctx
->readPending_ready
, (unsigned)ctx
->state
);
107 return errSSLProtocol
;
110 sslLogNegotiateDebug("===Processing changeCipherSpec msg");
112 /* Install new cipher spec on read side */
113 if ((err
= ctx
->recFuncs
->advanceReadCipher(ctx
->recCtx
)) != 0)
114 { SSLFatalSessionAlert(SSL_AlertInternalError
, ctx
);
117 ctx
->readCipher_ready
= 0; /* Can't send data until Finished is sent */
118 SSLChangeHdskState(ctx
, SSL_HdskStateFinished
);
119 return errSecSuccess
;