]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslUtils.cpp
Security-177.tar.gz
[apple/security.git] / SecureTransport / sslUtils.cpp
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 /*
20 File: sslutils.ccpp
21
22 Contains: Misc. SSL utility functions
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslContext.h"
31 #include "sslUtils.h"
32 #include "sslMemory.h"
33 #include "sslDebug.h"
34 #include <Security/devrandom.h>
35
36 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
37 #include <sys/time.h>
38
39 UInt32
40 SSLDecodeInt(const unsigned char *p, int length)
41 { UInt32 val = 0;
42 while (length--)
43 val = (val << 8) | *p++;
44 return val;
45 }
46
47 unsigned char *
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 */
53 value >>= 8;
54 }
55 return retVal;
56 }
57
58 UInt8*
59 SSLEncodeUInt64(UInt8 *p, sslUint64 value)
60 { p = SSLEncodeInt(p, value.high, 4);
61 return SSLEncodeInt(p, value.low, 4);
62 }
63
64
65 void
66 IncrementUInt64(sslUint64 *v)
67 { if (++v->low == 0) /* Must have just rolled over */
68 ++v->high;
69 }
70
71 UInt32
72 SSLGetCertificateChainLength(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
84 Boolean sslIsSessionActive(const SSLContext *ctx)
85 {
86 assert(ctx != NULL);
87 switch(ctx->state) {
88 case SSL_HdskStateUninit:
89 case SSL_HdskStateServerUninit:
90 case SSL_HdskStateClientUninit:
91 case SSL_HdskStateGracefulClose:
92 case SSL_HdskStateErrorClose:
93 return false;
94 default:
95 return true;
96 }
97 }
98
99 OSStatus sslDeleteCertificateChain(
100 SSLCertificate *certs,
101 SSLContext *ctx)
102 {
103 SSLCertificate *cert;
104 SSLCertificate *nextCert;
105
106 assert(ctx != NULL);
107 cert=certs;
108 while(cert != NULL) {
109 nextCert = cert->next;
110 SSLFreeBuffer(cert->derCert, ctx);
111 sslFree(cert);
112 cert = nextCert;
113 }
114 return noErr;
115 }
116
117 #if SSL_DEBUG
118
119 const char *protocolVersStr(SSLProtocolVersion prot)
120 {
121 switch(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";
127 }
128 return NULL; /* NOT REACHED */
129 }
130
131 #endif /* SSL_DEBUG */
132
133 /*
134 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
135 */
136 OSStatus 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
152 OSStatus 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
168 OSStatus 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 */
179 OSStatus 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
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 */
205 OSStatus 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 */
281 OSStatus 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