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