]>
Commit | Line | Data |
---|---|---|
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 | |
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 */ | |
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 |
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 | ||
bac41a7b A |
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 | { | |
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 | ||
99 | OSStatus 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 | ||
119 | const 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 | */ | |
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 | ||
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 | */ | |
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 |