2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
22 Contains: Misc. SSL utility functions
24 Written by: Doug Mitchell
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
30 #include "sslContext.h"
32 #include "sslMemory.h"
34 #include <Security/devrandom.h>
36 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
40 SSLDecodeInt(const unsigned char *p
, int length
)
43 val
= (val
<< 8) | *p
++;
48 SSLEncodeInt(unsigned char *p
, UInt32 value
, int length
)
49 { unsigned char *retVal
= p
+ length
; /* Return pointer to char after int */
50 assert(length
> 0 && length
<= 4);
51 while (length
--) /* Assemble backwards */
52 { p
[length
] = (UInt8
)value
; /* Implicit masking to low byte */
59 SSLEncodeUInt64(UInt8
*p
, sslUint64 value
)
60 { p
= SSLEncodeInt(p
, value
.high
, 4);
61 return SSLEncodeInt(p
, value
.low
, 4);
66 IncrementUInt64(sslUint64
*v
)
67 { if (++v
->low
== 0) /* Must have just rolled over */
72 SSLGetCertificateChainLength(const SSLCertificate
*c
)
84 Boolean
sslIsSessionActive(const SSLContext
*ctx
)
88 case SSL_HdskStateUninit
:
89 case SSL_HdskStateServerUninit
:
90 case SSL_HdskStateClientUninit
:
91 case SSL_HdskStateGracefulClose
:
92 case SSL_HdskStateErrorClose
:
99 OSStatus
sslDeleteCertificateChain(
100 SSLCertificate
*certs
,
103 SSLCertificate
*cert
;
104 SSLCertificate
*nextCert
;
108 while(cert
!= NULL
) {
109 nextCert
= cert
->next
;
110 SSLFreeBuffer(cert
->derCert
, ctx
);
119 const char *protocolVersStr(SSLProtocolVersion prot
)
122 case SSL_Version_Undetermined
: return "SSL_Version_Undetermined";
123 case SSL_Version_2_0
: return "SSL_Version_2_0";
124 case SSL_Version_3_0
: return "SSL_Version_3_0";
125 case TLS_Version_1_0
: return "TLS_Version_1_0";
126 default: sslErrorLog("protocolVersStr: bad prot\n"); return "BAD PROTOCOL";
128 return NULL
; /* NOT REACHED */
131 #endif /* SSL_DEBUG */
134 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
138 size_t *actualLength
,
141 UInt32 dataLength
= buf
.length
;
145 ortn
= (ctx
->ioCtx
.read
)(ctx
->ioCtx
.ioRef
,
148 *actualLength
= dataLength
;
154 size_t *actualLength
,
157 UInt32 dataLength
= buf
.length
;
161 ortn
= (ctx
->ioCtx
.write
)(ctx
->ioCtx
.ioRef
,
164 *actualLength
= dataLength
;
168 OSStatus
sslTime(UInt32
*tim
)
177 * Common RNG function.
179 OSStatus
sslRand(SSLContext
*ctx
, SSLBuffer
*buf
)
181 OSStatus serr
= noErr
;
185 assert(buf
->data
!= NULL
);
187 if(buf
->length
== 0) {
188 sslErrorLog("sslRand: zero buf->length\n");
192 Security::DevRandomGenerator
devRand(false);
193 devRand
.random(buf
->data
, buf
->length
);
202 * Given a protocol version sent by peer, determine if we accept that version
203 * and downgrade if appropriate (which can not be done for the client side).
205 OSStatus
sslVerifyProtVersion(
207 SSLProtocolVersion peerVersion
, // sent by peer
208 SSLProtocolVersion
*negVersion
) // final negotiated version if return success
210 OSStatus ortn
= noErr
;
212 switch(peerVersion
) {
213 case SSL_Version_2_0
:
214 if(ctx
->versionSsl2Enable
) {
215 *negVersion
= SSL_Version_2_0
;
218 /* SSL2 is the best peer can do but we don't support it */
219 ortn
= errSSLNegotiation
;
222 case SSL_Version_3_0
:
223 if(ctx
->versionSsl3Enable
) {
224 *negVersion
= SSL_Version_3_0
;
226 /* downgrade if possible */
227 else if(ctx
->protocolSide
== SSL_ClientSide
) {
228 /* client side - no more negotiation possible */
229 ortn
= errSSLNegotiation
;
231 else if(ctx
->versionSsl2Enable
) {
232 /* server downgrading to SSL2 */
233 *negVersion
= SSL_Version_2_0
;
236 /* Peer requested SSL3, we don't support SSL2 or SSL3 */
237 ortn
= errSSLNegotiation
;
240 case TLS_Version_1_0
:
241 if(ctx
->versionTls1Enable
) {
242 *negVersion
= TLS_Version_1_0
;
244 /* downgrade if possible */
245 else if(ctx
->protocolSide
== SSL_ClientSide
) {
247 * Client side - no more negotiation possible
248 * Note this actually implies a pretty serious server
249 * side violation; it's sending back a protocol version
250 * HIGHER than we requested
252 ortn
= errSSLNegotiation
;
254 else if(ctx
->versionSsl3Enable
) {
255 /* server downgrading to SSL3 */
256 *negVersion
= SSL_Version_3_0
;
258 else if(ctx
->versionSsl2Enable
) {
259 /* server downgrading to SSL2 */
260 *negVersion
= SSL_Version_2_0
;
263 /* we appear not to support any protocol */
264 sslErrorLog("sslVerifyProtVersion: no protocols supported\n");
265 ortn
= errSSLNegotiation
;
269 ortn
= errSSLNegotiation
;
277 * Determine max enabled protocol, i.e., the one we try to negotiate for.
278 * Only returns an error (paramErr) if NO protocols are enabled, which can
279 * in fact happen by malicious or ignorant use of SSLSetProtocolVersionEnabled().
281 OSStatus
sslGetMaxProtVersion(
283 SSLProtocolVersion
*version
) // RETURNED
285 OSStatus ortn
= noErr
;
286 if(ctx
->versionTls1Enable
) {
287 *version
= TLS_Version_1_0
;
289 else if(ctx
->versionSsl3Enable
) {
290 *version
= SSL_Version_3_0
;
292 else if(ctx
->versionSsl2Enable
) {
293 *version
= SSL_Version_2_0
;