]> git.saurik.com Git - apple/security.git/blame - SecureTransport/sslUtils.cpp
Security-176.tar.gz
[apple/security.git] / SecureTransport / sslUtils.cpp
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19/*
df0e469f 20 File: sslutils.ccpp
bac41a7b
A
21
22 Contains: Misc. SSL utility functions
23
5a719ac8 24 Written by: Doug Mitchell
bac41a7b
A
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28*/
bac41a7b 29
5a719ac8
A
30#include "sslContext.h"
31#include "sslUtils.h"
32#include "sslMemory.h"
bac41a7b 33#include "sslDebug.h"
5a719ac8 34#include <Security/devrandom.h>
bac41a7b
A
35
36#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
5a719ac8 37#include <sys/time.h>
bac41a7b
A
38
39UInt32
40SSLDecodeInt(const unsigned char *p, int length)
41{ UInt32 val = 0;
42 while (length--)
43 val = (val << 8) | *p++;
44 return val;
45}
46
47unsigned char *
48SSLEncodeInt(unsigned char *p, UInt32 value, int length)
49{ unsigned char *retVal = p + length; /* Return pointer to char after int */
5a719ac8 50 assert(length > 0 && length <= 4);
bac41a7b
A
51 while (length--) /* Assemble backwards */
52 { p[length] = (UInt8)value; /* Implicit masking to low byte */
53 value >>= 8;
54 }
55 return retVal;
56}
57
29654253
A
58UInt8*
59SSLEncodeUInt64(UInt8 *p, sslUint64 value)
60{ p = SSLEncodeInt(p, value.high, 4);
61 return SSLEncodeInt(p, value.low, 4);
62}
63
64
bac41a7b
A
65void
66IncrementUInt64(sslUint64 *v)
67{ if (++v->low == 0) /* Must have just rolled over */
68 ++v->high;
69}
70
71UInt32
72SSLGetCertificateChainLength(const SSLCertificate *c)
73{
74 UInt32 rtn = 0;
75
76 while (c)
77 {
78 rtn++;
79 c = c->next;
80 }
81 return rtn;
82}
83
84Boolean sslIsSessionActive(const SSLContext *ctx)
85{
5a719ac8 86 assert(ctx != NULL);
bac41a7b 87 switch(ctx->state) {
5a719ac8
A
88 case SSL_HdskStateUninit:
89 case SSL_HdskStateServerUninit:
90 case SSL_HdskStateClientUninit:
91 case SSL_HdskStateGracefulClose:
92 case SSL_HdskStateErrorClose:
bac41a7b
A
93 return false;
94 default:
95 return true;
96 }
97}
98
99OSStatus sslDeleteCertificateChain(
100 SSLCertificate *certs,
101 SSLContext *ctx)
102{
103 SSLCertificate *cert;
104 SSLCertificate *nextCert;
105
5a719ac8 106 assert(ctx != NULL);
bac41a7b
A
107 cert=certs;
108 while(cert != NULL) {
109 nextCert = cert->next;
5a719ac8 110 SSLFreeBuffer(cert->derCert, ctx);
bac41a7b
A
111 sslFree(cert);
112 cert = nextCert;
113 }
114 return noErr;
115}
116
117#if SSL_DEBUG
118
119const char *protocolVersStr(SSLProtocolVersion prot)
120{
121 switch(prot) {
122 case SSL_Version_Undetermined: return "SSL_Version_Undetermined";
bac41a7b
A
123 case SSL_Version_2_0: return "SSL_Version_2_0";
124 case SSL_Version_3_0: return "SSL_Version_3_0";
29654253 125 case TLS_Version_1_0: return "TLS_Version_1_0";
5a719ac8 126 default: sslErrorLog("protocolVersStr: bad prot\n"); return "BAD PROTOCOL";
bac41a7b
A
127 }
128 return NULL; /* NOT REACHED */
129}
130
131#endif /* SSL_DEBUG */
5a719ac8
A
132
133/*
134 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
135 */
136OSStatus sslIoRead(
137 SSLBuffer buf,
138 size_t *actualLength,
139 SSLContext *ctx)
140{
141 UInt32 dataLength = buf.length;
142 OSStatus ortn;
143
144 *actualLength = 0;
145 ortn = (ctx->ioCtx.read)(ctx->ioCtx.ioRef,
146 buf.data,
147 &dataLength);
148 *actualLength = dataLength;
149 return ortn;
150}
151
152OSStatus sslIoWrite(
153 SSLBuffer buf,
154 size_t *actualLength,
155 SSLContext *ctx)
156{
157 UInt32 dataLength = buf.length;
158 OSStatus ortn;
159
160 *actualLength = 0;
161 ortn = (ctx->ioCtx.write)(ctx->ioCtx.ioRef,
162 buf.data,
163 &dataLength);
164 *actualLength = dataLength;
165 return ortn;
166}
167
168OSStatus sslTime(UInt32 *tim)
169{
170 time_t t;
171 time(&t);
172 *tim = (UInt32)t;
173 return noErr;
174}
175
176/*
177 * Common RNG function.
178 */
179OSStatus sslRand(SSLContext *ctx, SSLBuffer *buf)
180{
181 OSStatus serr = noErr;
182
183 assert(ctx != NULL);
184 assert(buf != NULL);
185 assert(buf->data != NULL);
186
187 if(buf->length == 0) {
188 sslErrorLog("sslRand: zero buf->length\n");
189 return noErr;
190 }
191 try {
192 Security::DevRandomGenerator devRand(false);
193 devRand.random(buf->data, buf->length);
194 }
195 catch(...) {
196 serr = errSSLCrypto;
197 }
198 return serr;
199}
200
df0e469f
A
201/*
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).
204 */
205OSStatus sslVerifyProtVersion(
206 SSLContext *ctx,
207 SSLProtocolVersion peerVersion, // sent by peer
208 SSLProtocolVersion *negVersion) // final negotiated version if return success
209{
210 OSStatus ortn = noErr;
211
212 switch(peerVersion) {
213 case SSL_Version_2_0:
214 if(ctx->versionSsl2Enable) {
215 *negVersion = SSL_Version_2_0;
216 }
217 else {
218 /* SSL2 is the best peer can do but we don't support it */
219 ortn = errSSLNegotiation;
220 }
221 break;
222 case SSL_Version_3_0:
223 if(ctx->versionSsl3Enable) {
224 *negVersion = SSL_Version_3_0;
225 }
226 /* downgrade if possible */
227 else if(ctx->protocolSide == SSL_ClientSide) {
228 /* client side - no more negotiation possible */
229 ortn = errSSLNegotiation;
230 }
231 else if(ctx->versionSsl2Enable) {
232 /* server downgrading to SSL2 */
233 *negVersion = SSL_Version_2_0;
234 }
235 else {
236 /* Peer requested SSL3, we don't support SSL2 or SSL3 */
237 ortn = errSSLNegotiation;
238 }
239 break;
240 case TLS_Version_1_0:
241 if(ctx->versionTls1Enable) {
242 *negVersion = TLS_Version_1_0;
243 }
244 /* downgrade if possible */
245 else if(ctx->protocolSide == SSL_ClientSide) {
246 /*
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
251 */
252 ortn = errSSLNegotiation;
253 }
254 else if(ctx->versionSsl3Enable) {
255 /* server downgrading to SSL3 */
256 *negVersion = SSL_Version_3_0;
257 }
258 else if(ctx->versionSsl2Enable) {
259 /* server downgrading to SSL2 */
260 *negVersion = SSL_Version_2_0;
261 }
262 else {
263 /* we appear not to support any protocol */
264 sslErrorLog("sslVerifyProtVersion: no protocols supported\n");
265 ortn = errSSLNegotiation;
266 }
267 break;
268 default:
269 ortn = errSSLNegotiation;
270 break;
271
272 }
273 return ortn;
274}
275
276/*
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().
280 */
281OSStatus sslGetMaxProtVersion(
282 SSLContext *ctx,
283 SSLProtocolVersion *version) // RETURNED
284{
285 OSStatus ortn = noErr;
286 if(ctx->versionTls1Enable) {
287 *version = TLS_Version_1_0;
288 }
289 else if(ctx->versionSsl3Enable) {
290 *version = SSL_Version_3_0;
291 }
292 else if(ctx->versionSsl2Enable) {
293 *version = SSL_Version_2_0;
294 }
295 else {
296 ortn = paramErr;
297 }
298 return ortn;
299}
300
301