]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+split.m
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+split.m
1 #include <stdbool.h>
2 #include <pthread.h>
3 #include <fcntl.h>
4 #include <sys/mman.h>
5 #include <unistd.h>
6
7 #include <CoreFoundation/CoreFoundation.h>
8
9 #include <AssertMacros.h>
10 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
11 #include <Security/SecureTransport.h>
12 #include <Security/SecPolicy.h>
13 #include <Security/SecTrust.h>
14 #include <Security/SecIdentity.h>
15 #include <Security/SecIdentityPriv.h>
16 #include <Security/SecCertificatePriv.h>
17 #include <Security/SecKeyPriv.h>
18 #include <Security/SecItem.h>
19 #include <Security/SecRandom.h>
20
21 #include <utilities/SecCFRelease.h>
22
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <mach/mach_time.h>
29
30 #if TARGET_OS_IPHONE
31 #include <Security/SecRSAKey.h>
32 #endif
33
34 #include "ssl-utils.h"
35
36 #include <tls_stream_parser.h>
37 #import "STLegacyTests.h"
38
39 #pragma clang diagnostic push
40 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
41
42 @implementation STLegacyTests (split)
43
44 typedef struct {
45 SSLContextRef st;
46 bool is_server;
47 int comm;
48 CFArrayRef certs;
49 int write_counter;
50 tls_stream_parser_t parser;
51 size_t write_size;
52 } ssl_test_handle;
53
54
55 #pragma mark -
56 #pragma mark SecureTransport support
57
58 #if SECTRANS_VERBOSE_DEBUG
59 static void hexdump(const char *s, const uint8_t *bytes, size_t len) {
60 size_t ix;
61 printf("socket %s(%p, %lu)\n", s, bytes, len);
62 for (ix = 0; ix < len; ++ix) {
63 if (!(ix % 16))
64 printf("\n");
65 printf("%02X ", bytes[ix]);
66 }
67 printf("\n");
68 }
69 #else
70 #define hexdump(string, bytes, len)
71 #endif
72
73 static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length)
74 {
75 ssl_test_handle *handle =(ssl_test_handle *)h;
76 int conn = handle->comm;
77 size_t len = *length;
78 uint8_t *ptr = (uint8_t *)data;
79
80 if(handle->is_server) {
81 //printf("SocketWrite: server write len=%zd\n", len);
82
83 tls_buffer buffer;
84 buffer.data = ptr;
85 buffer.length = len;
86 tls_stream_parser_parse(handle->parser, buffer);
87 }
88
89 do {
90 ssize_t ret;
91 do {
92 hexdump("write", ptr, len);
93 ret = write((int)conn, ptr, len);
94 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
95 if (ret > 0) {
96 len -= ret;
97 ptr += ret;
98 }
99 else
100 return -36;
101 } while (len > 0);
102
103 *length = *length - len;
104 return errSecSuccess;
105 }
106
107 static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length)
108 {
109 const ssl_test_handle *handle=h;
110 int conn = handle->comm;
111 size_t len = *length;
112 uint8_t *ptr = (uint8_t *)data;
113
114
115 do {
116 ssize_t ret;
117 do {
118 ret = read((int)conn, ptr, len);
119 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
120 if (ret > 0) {
121 len -= ret;
122 ptr += ret;
123 }
124 else
125 return -36;
126 } while (len > 0);
127
128 if(len!=0)
129 printf("Something went wrong here... len=%d\n", (int)len);
130
131 *length = *length - len;
132 return errSecSuccess;
133 }
134
135 static int process(tls_stream_parser_ctx_t ctx, tls_buffer record)
136 {
137 ssl_test_handle *handle = (ssl_test_handle *)ctx;
138
139 // printf("processing record len=%zd, type=%d\n", record.length, record.data[0]);
140 if(record.data[0]==tls_record_type_AppData) {
141 handle->write_counter++;
142 // printf("record count = %d\n", handle->write_counter);
143 }
144
145 return 0;
146 }
147
148
149 static void *securetransport_ssl_thread(void *arg)
150 {
151 OSStatus ortn;
152 ssl_test_handle * ssl = (ssl_test_handle *)arg;
153 SSLContextRef ctx = ssl->st;
154 bool got_server_auth = false;
155
156 do {
157 ortn = SSLHandshake(ctx);
158
159 if (ortn == errSSLServerAuthCompleted) {
160 require_string(!got_server_auth, out, "second server auth");
161 got_server_auth = true;
162 }
163 } while (ortn == errSSLWouldBlock
164 || ortn == errSSLServerAuthCompleted);
165
166 require_noerr_action_quiet(ortn, out,
167 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
168
169 unsigned char ibuf[90000], obuf[45000];
170
171 if (ssl->is_server) {
172 size_t len;
173 require_action(errSecSuccess == SecRandomCopyBytes(kSecRandomDefault, ssl->write_size, obuf), out, ortn = -1);
174 require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out);
175 require_action(len == ssl->write_size, out, ortn = -1);
176 require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out);
177 require_action(len == ssl->write_size, out, ortn = -1);
178 } else {
179 size_t len = ssl->write_size*2;
180 size_t olen;
181 unsigned char *p = ibuf;
182 while (len) {
183 require_noerr(ortn = SSLRead(ctx, p, len, &olen), out);
184 len -= olen;
185 p += olen;
186 }
187 }
188
189 out:
190 SSLClose(ctx);
191 CFRelease(ctx);
192 close(ssl->comm);
193 pthread_exit((void *)(intptr_t)ortn);
194 return NULL;
195 }
196
197 static void
198 ssl_test_handle_destroy(ssl_test_handle *handle)
199 {
200 if (handle) {
201 if (handle->parser) {
202 tls_stream_parser_destroy(handle->parser);
203 }
204 free(handle);
205 }
206 }
207
208 static ssl_test_handle *
209 ssl_test_handle_create(bool server, int comm, CFArrayRef certs)
210 {
211 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
212 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType);
213
214 require(handle, out);
215 require(ctx, out);
216
217 require_noerr(SSLSetIOFuncs(ctx,
218 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
219 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out);
220
221 if (server) {
222 require_noerr(SSLSetCertificate(ctx, certs), out);
223 }
224
225 require_noerr(SSLSetSessionOption(ctx,
226 kSSLSessionOptionBreakOnServerAuth, true), out);
227
228 /* Tell SecureTransport to not check certs itself: it will break out of the
229 handshake to let us take care of it instead. */
230 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
231
232 handle->is_server = server;
233 handle->comm = comm;
234 handle->certs = certs;
235 handle->st = ctx;
236 handle->write_counter = 0;
237 handle->parser = tls_stream_parser_create(handle, process);
238
239 return handle;
240
241 out:
242 if (handle) free(handle);
243 if (ctx) CFRelease(ctx);
244 return NULL;
245 }
246
247 static SSLCipherSuite ciphers[] = {
248 TLS_RSA_WITH_AES_128_CBC_SHA,
249 };
250 static int nciphers = sizeof(ciphers)/sizeof(ciphers[0]);
251
252 static SSLProtocol versions[] = {
253 kSSLProtocol3,
254 kTLSProtocol1,
255 kTLSProtocol11,
256 kTLSProtocol12,
257 };
258 static int nversions = sizeof(versions)/sizeof(versions[0]);
259
260 // { write size, expected count when nosplit, expected count when split }
261 static size_t wsizes[][3] = {
262 { 1, 2, 2 },
263 { 2, 2, 3 },
264 { 3, 2, 3 },
265 { 4, 2, 3 },
266 { 16384, 2, 3 },
267 { 16385, 4, 4 },
268 { 16386, 4, 5 },
269 { 16387, 4, 5 },
270 { 16388, 4, 5 },
271 { 32768, 4, 5 },
272 { 32769, 6, 6 },
273 { 32770, 6, 7 },
274 { 32771, 6, 7 },
275 { 32772, 6, 7 },
276 };
277 static int nwsizes = sizeof(wsizes)/sizeof(wsizes[0]);
278
279 -(void) testSplit
280 {
281 pthread_t client_thread, server_thread;
282 CFArrayRef server_certs = server_chain();
283 XCTAssert(server_certs, "got server certs");
284
285 int i,j,k,s;
286
287 for(i=0; i<nciphers; i++)
288 for(j=0; j<nversions; j++)
289 for(k=0; k<nwsizes; k++)
290 for(s=0; s<3; s++)
291 {
292 int sp[2];
293 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
294 fcntl(sp[0], F_SETNOSIGPIPE, 1);
295 fcntl(sp[1], F_SETNOSIGPIPE, 1);
296
297 ssl_test_handle *server, *client;
298
299 server = ssl_test_handle_create(true /*server*/, sp[0], server_certs);
300 client = ssl_test_handle_create(false/*client*/, sp[1], NULL);
301
302 server->write_size = wsizes[k][0];
303 client->write_size = wsizes[k][0];
304
305 require(client, out);
306 require(server, out);
307
308 require_noerr(SSLSetProtocolVersionMin(server->st, kSSLProtocol3), out); // We need this server to do SSL3.
309 require_noerr(SSLSetProtocolVersionMax(client->st, versions[j]), out);
310 require_noerr(SSLSetEnabledCiphers(client->st, &ciphers[i], 1), out);
311 if(s) {
312 // s=0: default (should be enabled)
313 // s=1: explicit enable
314 // s=2: expliciti disable
315 require_noerr(SSLSetSessionOption(server->st, kSSLSessionOptionSendOneByteRecord, (s==1)?true:false), out);
316 }
317
318 pthread_create(&client_thread, NULL, securetransport_ssl_thread, client);
319 pthread_create(&server_thread, NULL, securetransport_ssl_thread, server);
320
321 intptr_t server_err, client_err;
322 pthread_join(client_thread, (void*)&client_err);
323 pthread_join(server_thread, (void*)&server_err);
324
325 XCTAssert(!server_err, "Server error = %ld", server_err);
326 XCTAssert(!client_err, "Client error = %ld", client_err);
327
328 /* one byte split is expected only for AES when using TLS 1.0 or lower, and when not disabled */
329 bool expected_split = (i==0) && (s!=2) && (versions[j]<=kTLSProtocol1);
330 int expected_count = (int)(expected_split ? wsizes[k][2]: wsizes[k][1]);
331
332 XCTAssertEqual(server->write_counter, expected_count, "wrong number of data records");
333
334
335 out:
336 ssl_test_handle_destroy(client);
337 ssl_test_handle_destroy(server);
338
339 }
340 CFReleaseNull(server_certs);
341 }
342
343 @end
344
345 #pragma clang diagnostic pop