]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/ssl-44-crashes.c
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / ssl-44-crashes.c
1 /*
2 * Copyright (c) 2012-2015 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
26 #include <stdbool.h>
27 #include <pthread.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30 #include <unistd.h>
31
32 #include <CoreFoundation/CoreFoundation.h>
33
34 #include <AssertMacros.h>
35 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
36 #include <Security/SecureTransport.h>
37 #include <Security/SecPolicy.h>
38 #include <Security/SecTrust.h>
39 #include <Security/SecIdentity.h>
40 #include <Security/SecIdentityPriv.h>
41 #include <Security/SecCertificatePriv.h>
42 #include <Security/SecKeyPriv.h>
43 #include <Security/SecItem.h>
44 #include <Security/SecRandom.h>
45
46 #include <utilities/SecCFRelease.h>
47 #include <string.h>
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #include <errno.h>
51 #include <stdlib.h>
52 #include <mach/mach_time.h>
53
54 #if TARGET_OS_IPHONE
55 #include <Security/SecRSAKey.h>
56 #endif
57
58 #include "ssl_regressions.h"
59 #include "ssl-utils.h"
60
61
62 typedef struct {
63 SSLContextRef st;
64 bool is_server;
65 int comm;
66 CFArrayRef certs;
67 int test;
68 } ssl_test_handle;
69
70
71 #pragma mark -
72 #pragma mark SecureTransport support
73
74 #if 0
75 static void hexdump(const char *s, const uint8_t *bytes, size_t len) {
76 size_t ix;
77 printf("socket %s(%p, %lu)\n", s, bytes, len);
78 for (ix = 0; ix < len; ++ix) {
79 if (!(ix % 16))
80 printf("\n");
81 printf("%02X ", bytes[ix]);
82 }
83 printf("\n");
84 }
85 #else
86 #define hexdump(string, bytes, len)
87 #endif
88
89 static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length)
90 {
91 int conn = ((const ssl_test_handle *)h)->comm;
92 size_t len = *length;
93 uint8_t *ptr = (uint8_t *)data;
94
95 do {
96 ssize_t ret;
97 do {
98 hexdump("write", ptr, len);
99 ret = write((int)conn, ptr, len);
100 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
101 if (ret > 0) {
102 len -= ret;
103 ptr += ret;
104 }
105 else
106 return -36;
107 } while (len > 0);
108
109 *length = *length - len;
110 return errSecSuccess;
111 }
112
113 static int changepad=0;
114
115 static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length)
116 {
117 const ssl_test_handle *handle=h;
118 int conn = handle->comm;
119 size_t len = *length;
120 uint8_t *ptr = (uint8_t *)data;
121
122
123 do {
124 ssize_t ret;
125 do {
126 ret = read((int)conn, ptr, len);
127 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
128 if (ret > 0) {
129 len -= ret;
130 ptr += ret;
131 }
132 else
133 return -36;
134 } while (len > 0);
135
136 if(len!=0)
137 printf("Something went wrong here... len=%d\n", (int)len);
138
139 *length = *length - len;
140
141 ptr=data;
142
143 /* change pad in the data */
144 if(changepad==1) {
145 changepad=0;
146 ptr[31]=ptr[31]^0x08^0xff; // expected padding was 8, changing it to 0xff to trigger integer underflow.
147 }
148
149 /* We are reading the server cert */
150 if((ptr[0]==0x0b) && (handle->test==3)) {
151 #if 1 // cert length for TARGET_OS_IPHONE
152 size_t expected_len = 631;
153 #else
154 size_t expected_len = 500;
155 #endif
156 if(*length!=expected_len) {
157 fprintf(stderr, "Expected cert length %ld, got %ld... test might fail\n",
158 (long)expected_len, (long)*length);
159 }
160 ptr[0x16] = 0x4; // version = 4 certificate should cause error, but not crash .
161 }
162
163 /* We are reading a data application header */
164 if(*length==5 && ptr[0]==0x17) {
165 switch(handle->test) {
166 case 0:
167 ptr[4]=32; // reduce the size to 2 blocks and trigger integer underflow.
168 break;
169 case 1:
170 ptr[4]=48; // reduce the size to 3 blocks and triggering integer underflow in the padding.
171 break;
172 case 2:
173 changepad=1;
174 break;
175 default:
176 break;
177 }
178 }
179
180
181 return errSecSuccess;
182 }
183
184
185
186 static void *securetransport_ssl_thread(void *arg)
187 {
188 OSStatus ortn;
189 ssl_test_handle * ssl = (ssl_test_handle *)arg;
190 SSLContextRef ctx = ssl->st;
191 bool got_server_auth = false;
192
193 //uint64_t start = mach_absolute_time();
194 do {
195 ortn = SSLHandshake(ctx);
196
197 if (ortn == errSSLServerAuthCompleted)
198 {
199 require_string(!got_server_auth, out, "second server auth");
200 got_server_auth = true;
201 }
202 } while (ortn == errSSLWouldBlock
203 || ortn == errSSLServerAuthCompleted);
204
205 require_noerr_quiet(ortn, out);
206
207 unsigned char ibuf[8], obuf[8];
208 size_t len;
209 if (ssl->is_server) {
210 require_action_quiet(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf), out, ortn = -1);
211 require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out);
212 require_action_quiet(len == sizeof(obuf), out, ortn = -1);
213 } else {
214 require_noerr_quiet(ortn = SSLRead(ctx, ibuf, sizeof(ibuf), &len), out);
215 require_action_quiet(len == sizeof(ibuf), out, ortn = -1);
216 }
217
218 out:
219 SSLClose(ctx);
220 CFRelease(ctx);
221 close(ssl->comm);
222 pthread_exit((void *)(intptr_t)ortn);
223 return NULL;
224 }
225
226
227 static ssl_test_handle *
228 ssl_test_handle_create(bool server, int comm, CFArrayRef certs)
229 {
230 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
231 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType);
232
233 require(handle, out);
234 require(ctx, out);
235
236 require_noerr(SSLSetIOFuncs(ctx,
237 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
238 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out);
239
240 if (server)
241 require_noerr(SSLSetCertificate(ctx, certs), out);
242
243 require_noerr(SSLSetSessionOption(ctx,
244 kSSLSessionOptionBreakOnServerAuth, true), out);
245
246 /* Tell SecureTransport to not check certs itself: it will break out of the
247 handshake to let us take care of it instead. */
248 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
249
250 handle->is_server = server;
251 handle->comm = comm;
252 handle->certs = certs;
253 handle->st = ctx;
254
255 return handle;
256
257 out:
258 if (handle) free(handle);
259 if (ctx) CFRelease(ctx);
260 return NULL;
261 }
262
263 static void
264 tests(void)
265 {
266 pthread_t client_thread, server_thread;
267 CFArrayRef server_certs = server_chain();
268 ok(server_certs, "got server certs");
269
270 int i;
271
272 for(i=0; i<4; i++)
273 {
274 int sp[2];
275 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
276 fcntl(sp[0], F_SETNOSIGPIPE, 1);
277 fcntl(sp[1], F_SETNOSIGPIPE, 1);
278
279 ssl_test_handle *server, *client;
280
281 server = ssl_test_handle_create(true /*server*/, sp[0], server_certs);
282 client = ssl_test_handle_create(false/*client*/, sp[1], NULL);
283
284 server->test=i;
285 client->test=i;
286
287 require(client, out);
288 require(server, out);
289
290 SSLCipherSuite cipher = TLS_RSA_WITH_AES_128_CBC_SHA256;
291 require_noerr(SSLSetEnabledCiphers(client->st, &cipher, 1), out);
292
293 pthread_create(&client_thread, NULL, securetransport_ssl_thread, client);
294 pthread_create(&server_thread, NULL, securetransport_ssl_thread, server);
295
296 intptr_t server_err, client_err;
297 pthread_join(client_thread, (void*)&client_err);
298 pthread_join(server_thread, (void*)&server_err);
299
300 ok(server_err==((i==3)?errSSLPeerCertUnknown:0), "Server error = %zu (i=%d)", server_err, i);
301 /* tests 0/1 should cause errSSLClosedAbort, 2 should cause errSSLBadRecordMac, 3 should cause errSSLXCertChainInvalid */
302 ok(client_err==((i==3)?errSSLXCertChainInvalid:(i==2)?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %zu (i=%d)", client_err, i);
303
304 out:
305 free(client);
306 free(server);
307
308 }
309 CFReleaseNull(server_certs);
310 }
311
312 int ssl_44_crashes(int argc, char *const *argv)
313 {
314
315 plan_tests(4*2 + 1 /*cert*/);
316
317
318 tests();
319
320 return 0;
321 }