]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/sslUtils.c
Security-55178.0.1.tar.gz
[apple/security.git] / libsecurity_ssl / lib / sslUtils.c
1 /*
2 * Copyright (c) 1999-2001,2005-2008,2010-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * sslUtils.c - Misc. SSL utility functions
26 */
27
28 #include "sslContext.h"
29 #include "sslUtils.h"
30 #include "sslMemory.h"
31 #include "sslDebug.h"
32
33 #include <sys/time.h>
34
35 #include <fcntl.h> // for open
36 #include <unistd.h> // for read
37 #include <errno.h> // for errno
38 #include <Security/SecFramework.h>
39 #include <Security/SecRandom.h>
40
41 #ifndef NDEBUG
42 void SSLDump(const unsigned char *data, unsigned long len)
43 {
44 unsigned long i;
45 for(i=0;i<len;i++)
46 {
47 if((i&0xf)==0) printf("%04lx :",i);
48 printf(" %02x", data[i]);
49 if((i&0xf)==0xf) printf("\n");
50 }
51 printf("\n");
52 }
53 #endif
54
55 unsigned int
56 SSLDecodeInt(const uint8_t *p, size_t length)
57 {
58 unsigned int val = 0;
59 assert(length > 0 && length <= 4); //anything else would be an internal error.
60 while (length--)
61 val = (val << 8) | *p++;
62 return val;
63 }
64
65 uint8_t *
66 SSLEncodeInt(uint8_t *p, unsigned int value, size_t length)
67 {
68 unsigned char *retVal = p + length; /* Return pointer to char after int */
69 assert(length > 0 && length <= 4); //anything else would be an internal error.
70 while (length--) /* Assemble backwards */
71 { p[length] = (uint8_t)value; /* Implicit masking to low byte */
72 value >>= 8;
73 }
74 return retVal;
75 }
76
77 size_t
78 SSLDecodeSize(const uint8_t *p, size_t length)
79 {
80 unsigned int val = 0;
81 assert(length > 0 && length <= 4); //anything else would be an internal error.
82 while (length--)
83 val = (val << 8) | *p++;
84 return val;
85 }
86
87 uint8_t *
88 SSLEncodeSize(uint8_t *p, size_t value, size_t length)
89 {
90 unsigned char *retVal = p + length; /* Return pointer to char after int */
91 assert(length > 0 && length <= 4); //anything else would be an internal error.
92 while (length--) /* Assemble backwards */
93 { p[length] = (uint8_t)value; /* Implicit masking to low byte */
94 value >>= 8;
95 }
96 return retVal;
97 }
98
99
100 uint8_t *
101 SSLEncodeUInt64(uint8_t *p, sslUint64 value)
102 {
103 p = SSLEncodeInt(p, value.high, 4);
104 return SSLEncodeInt(p, value.low, 4);
105 }
106
107
108 uint8_t *
109 SSLEncodeHandshakeHeader(SSLContext *ctx, SSLRecord *rec, SSLHandshakeType type, size_t msglen)
110 {
111 uint8_t *charPtr;
112
113 charPtr = rec->contents.data;
114 *charPtr++ = type;
115 charPtr = SSLEncodeSize(charPtr, msglen, 3);
116
117 if(rec->protocolVersion == DTLS_Version_1_0) {
118 charPtr = SSLEncodeInt(charPtr, ctx->hdskMessageSeq, 2);
119 /* fragmentation -- we encode header as if unfragmented,
120 actual fragmentation happens at lower layer. */
121 charPtr = SSLEncodeInt(charPtr, 0, 3);
122 charPtr = SSLEncodeSize(charPtr, msglen, 3);
123 }
124
125 return charPtr;
126 }
127
128
129 void
130 IncrementUInt64(sslUint64 *v)
131 { if (++v->low == 0) /* Must have just rolled over */
132 ++v->high;
133 }
134
135 #if ENABLE_DTLS
136 void
137 SSLDecodeUInt64(const uint8_t *p, size_t length, sslUint64 *v)
138 {
139 assert(length > 0 && length <= 8);
140 if(length<=4) {
141 v->low=SSLDecodeInt(p, length);
142 v->high=0;
143 } else {
144 v->high=SSLDecodeInt(p, length-4);
145 v->low=SSLDecodeInt(p+length-4, 4);
146 }
147 }
148 #endif
149
150 #ifdef USE_SSLCERTIFICATE
151 size_t
152 SSLGetCertificateChainLength(const SSLCertificate *c)
153 {
154 size_t rtn = 0;
155
156 while (c)
157 {
158 rtn++;
159 c = c->next;
160 }
161 return rtn;
162 }
163
164 OSStatus sslDeleteCertificateChain(
165 SSLCertificate *certs,
166 SSLContext *ctx)
167 {
168 SSLCertificate *cert;
169 SSLCertificate *nextCert;
170
171 assert(ctx != NULL);
172 cert=certs;
173 while(cert != NULL) {
174 nextCert = cert->next;
175 SSLFreeBuffer(&cert->derCert, ctx);
176 sslFree(cert);
177 cert = nextCert;
178 }
179 return noErr;
180 }
181 #endif /* USE_SSLCERTIFICATE */
182
183 Boolean sslIsSessionActive(const SSLContext *ctx)
184 {
185 assert(ctx != NULL);
186 switch(ctx->state) {
187 case SSL_HdskStateUninit:
188 case SSL_HdskStateServerUninit:
189 case SSL_HdskStateClientUninit:
190 case SSL_HdskStateGracefulClose:
191 case SSL_HdskStateErrorClose:
192 return false;
193 default:
194 return true;
195 }
196 }
197
198 #if SSL_DEBUG
199
200 const char *protocolVersStr(SSLProtocolVersion prot)
201 {
202 switch(prot) {
203 case SSL_Version_Undetermined: return "SSL_Version_Undetermined";
204 case SSL_Version_2_0: return "SSL_Version_2_0";
205 case SSL_Version_3_0: return "SSL_Version_3_0";
206 case TLS_Version_1_0: return "TLS_Version_1_0";
207 case TLS_Version_1_1: return "TLS_Version_1_1";
208 case TLS_Version_1_2: return "TLS_Version_1_2";
209 default: sslErrorLog("protocolVersStr: bad prot\n"); return "BAD PROTOCOL";
210 }
211 return NULL; /* NOT REACHED */
212 }
213
214 #endif /* SSL_DEBUG */
215
216 /*
217 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
218 */
219 OSStatus sslIoRead(
220 SSLBuffer buf,
221 size_t *actualLength,
222 SSLContext *ctx)
223 {
224 size_t dataLength = buf.length;
225 OSStatus ortn;
226
227 *actualLength = 0;
228 ortn = (ctx->ioCtx.read)(ctx->ioCtx.ioRef,
229 buf.data,
230 &dataLength);
231 *actualLength = dataLength;
232 return ortn;
233 }
234
235 OSStatus sslIoWrite(
236 SSLBuffer buf,
237 size_t *actualLength,
238 SSLContext *ctx)
239 {
240 size_t dataLength = buf.length;
241 OSStatus ortn;
242
243 *actualLength = 0;
244 ortn = (ctx->ioCtx.write)(ctx->ioCtx.ioRef,
245 buf.data,
246 &dataLength);
247 *actualLength = dataLength;
248 return ortn;
249 }
250
251 OSStatus sslTime(uint32_t *tim)
252 {
253 time_t t;
254 time(&t);
255 *tim = (uint32_t)t;
256 return noErr;
257 }
258
259 /*
260 * Common RNG function.
261 */
262 OSStatus sslRand(SSLContext *ctx, SSLBuffer *buf)
263 {
264 assert(buf != NULL);
265 assert(buf->data != NULL);
266
267 if(buf->length == 0) {
268 sslErrorLog("sslRand: zero buf->length\n");
269 return noErr;
270 }
271
272 return SecRandomCopyBytes(kSecRandomDefault, buf->length, buf->data) ? errSSLCrypto : noErr;
273 }
274
275 /*
276 * Given a protocol version sent by peer, determine if we accept that version
277 * and downgrade if appropriate (which can not be done for the client side).
278 */
279 OSStatus sslVerifyProtVersion(
280 SSLContext *ctx,
281 SSLProtocolVersion peerVersion, // sent by peer
282 SSLProtocolVersion *negVersion) // final negotiated version if return success
283 {
284 if ((ctx->isDTLS)
285 ? peerVersion > ctx->minProtocolVersion
286 : peerVersion < ctx->minProtocolVersion) {
287 return errSSLNegotiation;
288 }
289 if ((ctx->isDTLS)
290 ? peerVersion < ctx->maxProtocolVersion
291 : peerVersion > ctx->maxProtocolVersion) {
292 if (ctx->protocolSide == kSSLClientSide) {
293 return errSSLNegotiation;
294 }
295 *negVersion = ctx->maxProtocolVersion;
296 } else {
297 *negVersion = peerVersion;
298 }
299
300 return noErr;
301 }
302
303 /*
304 * Determine max enabled protocol, i.e., the one we try to negotiate for.
305 * Only returns an error (paramErr) if NO protocols are enabled, which can
306 * in fact happen by malicious or ignorant use of SSLSetProtocolVersionEnabled().
307 */
308 OSStatus sslGetMaxProtVersion(
309 SSLContext *ctx,
310 SSLProtocolVersion *version) // RETURNED
311 {
312 /* This check is here until SSLSetProtocolVersionEnabled() is gone .*/
313 if (ctx->maxProtocolVersion == SSL_Version_Undetermined)
314 return badReqErr;
315
316 *version = ctx->maxProtocolVersion;
317 return noErr;
318 }