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