]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/regressions/SecureTransportTests/STLegacyTests+ciphers.m
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / regressions / SecureTransportTests / STLegacyTests+ciphers.m
1 #include <AssertMacros.h>
2 #import "STLegacyTests.h"
3 #include <stdbool.h>
4 #include <pthread.h>
5 #include <fcntl.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8
9 #include <CoreFoundation/CoreFoundation.h>
10
11 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
12 #include <Security/SecureTransport.h>
13 #include <Security/SecPolicy.h>
14 #include <Security/SecTrust.h>
15 #include <Security/SecIdentity.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <Security/SecCertificatePriv.h>
18 #include <Security/SecKeyPriv.h>
19 #include <Security/SecItem.h>
20 #include <Security/SecRandom.h>
21
22 #include <utilities/array_size.h>
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 #include <tls_ciphersuites.h>
31
32 #if TARGET_OS_IPHONE
33 #include <Security/SecRSAKey.h>
34 #endif
35
36 #include "ssl-utils.h"
37
38 /*
39 SSL CipherSuite tests
40 */
41 @implementation STLegacyTests (ciphers)
42
43 static const SSLCipherSuite SupportedCipherSuites[] = {
44
45 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
46 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
47 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
48 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
49 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
50 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
51 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
52
53 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
54 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
55 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
56 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
57 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
58 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
59 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
60
61 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
62 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
63 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
64 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
65 TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
66 TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
67 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
68
69 TLS_RSA_WITH_AES_256_GCM_SHA384,
70 TLS_RSA_WITH_AES_128_GCM_SHA256,
71 TLS_RSA_WITH_AES_256_CBC_SHA256,
72 TLS_RSA_WITH_AES_128_CBC_SHA256,
73 TLS_RSA_WITH_AES_256_CBC_SHA,
74 TLS_RSA_WITH_AES_128_CBC_SHA,
75 SSL_RSA_WITH_3DES_EDE_CBC_SHA,
76
77 /* Unsafe ciphersuites */
78
79 TLS_DH_anon_WITH_AES_256_GCM_SHA384,
80 TLS_DH_anon_WITH_AES_128_GCM_SHA256,
81 TLS_DH_anon_WITH_AES_128_CBC_SHA256,
82 TLS_DH_anon_WITH_AES_256_CBC_SHA256,
83 TLS_DH_anon_WITH_AES_128_CBC_SHA,
84 TLS_DH_anon_WITH_AES_256_CBC_SHA,
85 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
86
87 TLS_ECDH_anon_WITH_NULL_SHA,
88 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
89 TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
90 TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
91
92 TLS_ECDHE_ECDSA_WITH_NULL_SHA,
93 TLS_ECDHE_RSA_WITH_NULL_SHA,
94
95 TLS_PSK_WITH_AES_256_CBC_SHA384,
96 TLS_PSK_WITH_AES_128_CBC_SHA256,
97 TLS_PSK_WITH_AES_256_CBC_SHA,
98 TLS_PSK_WITH_AES_128_CBC_SHA,
99 TLS_PSK_WITH_3DES_EDE_CBC_SHA,
100 TLS_PSK_WITH_NULL_SHA384,
101 TLS_PSK_WITH_NULL_SHA256,
102 TLS_PSK_WITH_NULL_SHA,
103
104 TLS_RSA_WITH_NULL_SHA256,
105 SSL_RSA_WITH_NULL_SHA,
106 SSL_RSA_WITH_NULL_MD5
107
108 };
109
110 static const unsigned SupportedCipherSuitesCount = sizeof(SupportedCipherSuites)/sizeof(SupportedCipherSuites[0]);
111
112
113 static int protos[]={kTLSProtocol1, kTLSProtocol11, kTLSProtocol12, kDTLSProtocol1 };
114 static int nprotos = sizeof(protos)/sizeof(protos[0]);
115
116
117 static unsigned char dh_param_1024_bytes[] = {
118 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xf2, 0x56, 0xb9, 0x41, 0x74,
119 0x8c, 0x54, 0x22, 0xad, 0x94, 0x2b, 0xed, 0x83, 0xb9, 0xa0, 0x2f, 0x40,
120 0xce, 0xf8, 0xec, 0x96, 0xed, 0xcd, 0x8e, 0xfc, 0xf8, 0xdd, 0x06, 0x15,
121 0xbc, 0x68, 0x0d, 0x0e, 0x2c, 0xef, 0x00, 0x71, 0x28, 0x3d, 0x27, 0x6d,
122 0x5e, 0x42, 0x8c, 0xbd, 0x0f, 0x07, 0x23, 0x9d, 0x07, 0x8e, 0x52, 0x47,
123 0xa2, 0x5d, 0xf8, 0xd9, 0x9a, 0x7b, 0xb4, 0xab, 0xd2, 0xa3, 0x39, 0xe9,
124 0x2c, 0x3b, 0x9b, 0xaa, 0xbe, 0x4e, 0x01, 0x36, 0x16, 0xc2, 0x9e, 0x7b,
125 0x38, 0x78, 0x82, 0xd0, 0xed, 0x8e, 0x1e, 0xce, 0xa6, 0x23, 0x95, 0xae,
126 0x31, 0x66, 0x58, 0x60, 0x44, 0xdf, 0x1f, 0x9c, 0x68, 0xbf, 0x8b, 0xf1,
127 0xb4, 0xa8, 0xe7, 0xb2, 0x43, 0x8b, 0xa9, 0x3d, 0xa1, 0xb7, 0x1a, 0x11,
128 0xcf, 0xf4, 0x5e, 0xf7, 0x08, 0xf6, 0x84, 0x1c, 0xd7, 0xfa, 0x40, 0x10,
129 0xdc, 0x64, 0x83, 0x02, 0x01, 0x02
130 };
131 static unsigned char *dh_param_der = dh_param_1024_bytes;
132 static unsigned int dh_param_der_len = sizeof(dh_param_1024_bytes);
133
134
135 typedef struct {
136 uint32_t session_id;
137 bool is_session_resume;
138 SSLContextRef st;
139 bool is_server;
140 bool is_dtls;
141 SSLAuthenticate client_side_auth;
142 bool dh_anonymous;
143 int comm;
144 CFArrayRef certs;
145 CFArrayRef peer_certs;
146 SSLProtocol proto;
147 uint64_t time; // output
148 } ssl_test_handle;
149
150 #if 0 // currently unused
151 static CFArrayRef SecIdentityCopySSLClientAuthenticationChain(SecIdentityRef identity)
152 {
153 CFMutableArrayRef chain = NULL;
154 SecPolicyRef policy = NULL;
155 SecTrustRef trust = NULL;
156 SecTrustResultType trust_result;
157
158 do {
159 policy = SecPolicyCreateSSL(false, NULL);
160 if (!policy)
161 break;
162
163 SecCertificateRef cert = NULL;
164 if (SecIdentityCopyCertificate(identity, &cert))
165 break;
166
167 CFArrayRef certs = CFArrayCreate(NULL, (const void **)&cert,
168 1, &kCFTypeArrayCallBacks);
169 CFRelease(cert);
170 if (!certs)
171 break;
172
173 if (SecTrustCreateWithCertificates(certs, policy, &trust))
174 break;
175 CFRelease(certs);
176 CFRelease(policy);
177 if (SecTrustEvaluate(trust, &trust_result))
178 break;
179
180 int i, count = SecTrustGetCertificateCount(trust);
181 chain = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
182 CFArrayAppendValue(chain, identity);
183 for (i = 1; i < count; i++) {
184 if ((i+1 == count) && (trust_result == kSecTrustResultUnspecified))
185 continue; /* skip anchor if chain is complete */
186 SecCertificateRef s = SecTrustGetCertificateAtIndex(trust, i);
187 CFArrayAppendValue(chain, s);
188 }
189 } while (0);
190 if (trust)
191 CFRelease(trust);
192 if (policy)
193 CFRelease(policy);
194 return chain;
195 }
196 #endif // currently unused
197
198 // MARK: -
199 // MARK: SecureTransport support
200
201 #if 0
202 static void hexdump(const uint8_t *bytes, size_t len) {
203 size_t ix;
204 printf("socket write(%p, %lu)\n", bytes, len);
205 for (ix = 0; ix < len; ++ix) {
206 if (!(ix % 16))
207 printf("\n");
208 printf("%02X ", bytes[ix]);
209 }
210 printf("\n");
211 }
212 #else
213 #define hexdump(bytes, len)
214 #endif
215
216 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
217 {
218 size_t len = *length;
219 uint8_t *ptr = (uint8_t *)data;
220
221 do {
222 ssize_t ret;
223 do {
224 hexdump(ptr, len);
225 ret = write((int)conn, ptr, len);
226 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
227 if (ret > 0) {
228 len -= ret;
229 ptr += ret;
230 }
231 else
232 return -36;
233 } while (len > 0);
234
235 *length = *length - len;
236 return errSecSuccess;
237 }
238
239 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
240 {
241 size_t len = *length;
242 uint8_t *ptr = (uint8_t *)data;
243
244 do {
245 ssize_t ret;
246 do {
247 ret = read((int)conn, ptr, len);
248 } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR));
249 if (ret > 0) {
250 len -= ret;
251 ptr += ret;
252 } else {
253 printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno);
254 return -errno;
255 }
256 } while (len > 0);
257
258 *length = *length - len;
259 return errSecSuccess;
260 }
261
262 static unsigned char dn[] = {
263 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
264 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
265 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e,
266 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41,
267 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
268 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
269 0x72, 0x69, 0x74, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
270 0x03, 0x13, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74
271 };
272 static unsigned int dn_len = 96;
273
274 static SSLContextRef make_ssl_ref(bool server, SSLAuthenticate client_side_auth, bool dh_anonymous,
275 bool dtls, int sock, CFArrayRef certs, SSLProtocol proto)
276 {
277 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, dtls?kSSLDatagramType:kSSLStreamType);
278 require(ctx, out);
279
280 if(dtls) {
281 size_t mtu;
282 require_noerr(SSLSetMaxDatagramRecordSize(ctx, 400), out);
283 require_noerr(SSLGetMaxDatagramRecordSize(ctx, &mtu), out);
284 }
285 require_noerr(SSLSetProtocolVersionMax(ctx, proto), out);
286
287 require_noerr(SSLSetIOFuncs(ctx,
288 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
289 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
290 static const char *peer_domain_name = "localhost";
291 require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
292 strlen(peer_domain_name)), out);
293
294 require_noerr(SSLSetMinimumDHGroupSize(ctx, 512), out);
295
296 if (!dh_anonymous) {
297 if (server)
298 require_noerr(SSLSetCertificate(ctx, certs), out);
299 if ((client_side_auth != kNeverAuthenticate) && server) {
300 SSLAuthenticate auth;
301 require_noerr(SSLSetClientSideAuthenticate(ctx, client_side_auth), out);
302 require_noerr(SSLGetClientSideAuthenticate(ctx, &auth), out);
303 require(auth==client_side_auth, out);
304 require_noerr(SSLAddDistinguishedName(ctx, dn, dn_len), out);
305 }
306 #if 0 /* Setting client certificate in advance */
307 if ((client_side_auth == kAlwaysAuthenticate) && !server)
308 require_noerr(SSLSetCertificate(ctx, certs), out);
309 #endif
310 if ((client_side_auth != kNeverAuthenticate) && !server) /* enable break from SSLHandshake */
311 require_noerr(SSLSetSessionOption(ctx,
312 kSSLSessionOptionBreakOnCertRequested, true), out);
313 }
314
315 /* Set this option, even if doing anonDH or PSK - it should NOT break out in those case */
316 require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, true), out);
317
318 /* Tell SecureTransport to not check certs itself: it will break out of the
319 handshake to let us take care of it instead. */
320 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
321
322 if (server) {
323 require_noerr(SSLSetDiffieHellmanParams(ctx,
324 dh_param_der, dh_param_der_len), out);
325 }
326 else /* if client */ {
327 }
328
329 return ctx;
330 out:
331 if (ctx)
332 CFRelease(ctx);
333 return NULL;
334 }
335
336 static bool check_peer_cert(SSLContextRef ctx, const ssl_test_handle *ssl, SecTrustRef *trust)
337 {
338 CFMutableArrayRef peer_cert_array = NULL;
339 CFMutableArrayRef orig_peer_cert_array = NULL;
340
341 /* verify peer cert chain */
342 require_noerr(SSLCopyPeerTrust(ctx, trust), out);
343 SecTrustResultType trust_result = 0;
344 /* this won't verify without setting up a trusted anchor */
345 require_noerr(SecTrustEvaluate(*trust, &trust_result), out);
346
347 CFIndex n_certs = SecTrustGetCertificateCount(*trust);
348
349 peer_cert_array = CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks);
350 orig_peer_cert_array = CFArrayCreateMutableCopy(NULL, n_certs, ssl->peer_certs);
351 while (n_certs--)
352 CFArrayInsertValueAtIndex(peer_cert_array, 0,
353 SecTrustGetCertificateAtIndex(*trust, n_certs));
354
355 SecIdentityRef ident =
356 (SecIdentityRef)CFArrayGetValueAtIndex(orig_peer_cert_array, 0);
357 SecCertificateRef peer_cert = NULL;
358 require_noerr(SecIdentityCopyCertificate(ident, &peer_cert), out);
359 CFArraySetValueAtIndex(orig_peer_cert_array, 0, peer_cert);
360 CFRelease(peer_cert);
361
362 require(CFEqual(orig_peer_cert_array, peer_cert_array), out);
363 CFReleaseNull(orig_peer_cert_array);
364 CFReleaseNull(peer_cert_array);
365
366 return true;
367 out:
368 CFReleaseNull(orig_peer_cert_array);
369 CFReleaseNull(peer_cert_array);
370 return false;
371 }
372
373
374 #include <mach/mach_time.h>
375
376 #define perf_start() uint64_t _perf_time = mach_absolute_time();
377 #define perf_scale_factor() ({struct mach_timebase_info info; mach_timebase_info(&info); ((double)info.numer) / (1000000.0 * info.denom);})
378 #define perf_time() ((mach_absolute_time() - _perf_time) * perf_scale_factor())
379
380
381 static void *securetransport_ssl_thread(void *arg)
382 {
383 OSStatus ortn;
384 ssl_test_handle * ssl = (ssl_test_handle *)arg;
385 SSLContextRef ctx = ssl->st;
386 SecTrustRef trust = NULL;
387 bool got_server_auth = false, got_client_cert_req = false;
388 SSLSessionState ssl_state;
389
390 perf_start();
391
392 pthread_setname_np(ssl->is_server?"server thread":"client thread");
393
394 require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out);
395 require_action(ssl_state==kSSLIdle, out, ortn = -1);
396
397 do {
398 ortn = SSLHandshake(ctx);
399 require_noerr(SSLGetSessionState(ctx,&ssl_state), out);
400
401 if (ortn == errSSLPeerAuthCompleted)
402 {
403 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
404 require_string(!got_server_auth, out, "second server auth");
405 require_string(!ssl->dh_anonymous, out, "server auth with anon cipher");
406 // Note: Previously, the implementation always returned errSSLPeerAuthCompleted before
407 // errSSLClientCertRequested. Due to OCSP stappling implementation, this is no longer guaranteed.
408 // This behavior change should not be an issue, but it's possible that some applications will
409 // have issue with this new behavior. If we do find out that this is causing an issue, then
410 // the following require statement should be re-enabled, and the implementation changed
411 // to implement the former behavior.
412 //require_string(!got_client_cert_req, out, "got client cert req before server auth");
413 got_server_auth = true;
414 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
415 require_string(check_peer_cert(ctx, ssl, &trust), out, "Certificate check failed");
416 } else if (ortn == errSSLClientCertRequested) {
417 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
418 require_string(!got_client_cert_req, out, "second client cert req");
419 // Note: see Note above.
420 //require_string(got_server_auth, out, "didn't get server auth first");
421 got_client_cert_req = true;
422
423 /* set client cert */
424 require_string(!ssl->is_server, out, "errSSLClientCertRequested while running server");
425 require_string(!ssl->dh_anonymous, out, "errSSLClientCertRequested while running anon DH");
426
427 CFArrayRef DNs = NULL;
428 require_noerr(SSLCopyDistinguishedNames (ctx, &DNs), out);
429 require(DNs, out);
430 CFRelease(DNs);
431
432 require_string(ssl->client_side_auth != kNeverAuthenticate, out, "errSSLClientCertRequested in run not testing that");
433 if(ssl->client_side_auth == kAlwaysAuthenticate) { // Only set a client cert in mode 1.
434 require_noerr(SSLSetCertificate(ctx, ssl->certs), out);
435 }
436 } else if (ortn == errSSLWouldBlock) {
437 require_action(ssl_state==kSSLHandshake, out, ortn = -1);
438 }
439 } while (ortn == errSSLWouldBlock
440 || ortn == errSSLServerAuthCompleted
441 || ortn == errSSLClientCertRequested);
442 require_noerr_action_quiet(ortn, out,
443 fprintf(stderr, "Fell out of SSLHandshake with error: %d (%s)\n", (int)ortn, ssl->is_server?"server":"client"));
444
445 require_action(ssl_state==kSSLConnected, out, ortn = -1);
446
447 if (!ssl->is_server && !ssl->dh_anonymous && !ssl->is_session_resume) {
448 require_string(got_server_auth, out, "never got server auth");
449 if (ssl->client_side_auth != kNeverAuthenticate)
450 require_string(got_client_cert_req, out, "never got client cert req");
451 }
452
453 if (!ssl->is_server && !ssl->dh_anonymous && ssl->is_session_resume) {
454 require_string(!got_server_auth, out, "got server auth during resumption??");
455 require_string(check_peer_cert(ctx, ssl, &trust), out, "Certificate check failed (resumption case)");
456 }
457
458 SSLCipherSuite cipherSuite;
459 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
460
461 if(ssl->is_dtls) {
462 size_t sz;
463 SSLGetDatagramWriteSize(ctx, &sz);
464 }
465
466 Boolean sessionWasResumed = false;
467 uint8_t session_id_data[MAX_SESSION_ID_LENGTH];
468 size_t session_id_length = sizeof(session_id_data);
469 require_noerr_quiet(ortn = SSLGetResumableSessionInfo(ctx, &sessionWasResumed, session_id_data, &session_id_length), out);
470 require_action(ssl->dh_anonymous || (ssl->is_session_resume == sessionWasResumed), out, ortn = -1);
471
472 #define BUFSIZE (8*1024)
473 unsigned char ibuf[BUFSIZE], obuf[BUFSIZE];
474
475 for(int i=0; i<10; i++) {
476 size_t len;
477 if (ssl->is_server) {
478 memset(obuf, i, BUFSIZE);
479 require_noerr(ortn = SSLWrite(ctx, obuf, BUFSIZE, &len), out);
480 require_action(len == BUFSIZE, out, ortn = -1);
481
482 require_noerr(ortn = SSLWrite(ctx, obuf, 0, &len), out);
483 require_action(len == 0, out, ortn = -1);
484 }
485
486 len=0;
487 while(len<BUFSIZE) {
488 size_t l=len;
489 ortn = SSLRead(ctx, ibuf+len, BUFSIZE-len, &l);
490 len+=l;
491 }
492
493 require_noerr(ortn, out);
494 require_action(len == BUFSIZE, out, ortn = -1);
495
496 if (ssl->is_server) {
497 require_noerr(memcmp(ibuf, obuf, BUFSIZE), out);
498 } else {
499 require_noerr(ortn = SSLWrite(ctx, ibuf, BUFSIZE, &len), out);
500 require_action(len == BUFSIZE, out, ortn = -1);
501 }
502 }
503
504 out:
505 SSLClose(ctx);
506 CFRelease(ctx);
507 if (trust) CFRelease(trust);
508 close(ssl->comm);
509
510 ssl->time = perf_time();
511
512 pthread_exit((void *)(intptr_t)ortn);
513 return NULL;
514 }
515
516
517
518 static ssl_test_handle *
519 ssl_test_handle_create(uint32_t session_id, bool resume, bool server, SSLAuthenticate client_side_auth, bool dh_anonymous, bool dtls,
520 int comm, CFArrayRef certs, CFArrayRef peer_certs, SSLProtocol proto)
521 {
522 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
523 if (handle) {
524 handle->session_id = session_id;
525 handle->is_session_resume = resume;
526 handle->is_server = server;
527 handle->is_dtls = dtls;
528 handle->client_side_auth = client_side_auth;
529 handle->dh_anonymous = dh_anonymous;
530 handle->comm = comm;
531 handle->certs = certs;
532 handle->peer_certs = peer_certs;
533 handle->proto = proto;
534 handle->st = make_ssl_ref(server, client_side_auth, dh_anonymous, dtls, comm, certs, proto);
535 }
536 return handle;
537 }
538
539 -(void)testCiphers
540 {
541 pthread_t client_thread, server_thread;
542
543 CFArrayRef server_rsa_certs = server_chain();
544 CFArrayRef server_ec_certs = server_ec_chain();
545 CFArrayRef client_certs = trusted_client_chain();
546 XCTAssert(server_rsa_certs != NULL);
547 XCTAssert(server_ec_certs != NULL);
548 XCTAssert(client_certs != NULL);
549
550 int i,k,l, p;
551
552 for (p=0; p<nprotos; p++)
553 for (k=0; k<3; k++) /* client side auth mode:
554 0 (kSSLNeverAuthenticate): server doesn't request ,
555 1 (kSSLAlwaysAuthenticate): server request, client provide,
556 2 (kSSLTryAuthenticate): server request, client does not provide */
557 {
558
559 for (i=0; i<SupportedCipherSuitesCount; i++)
560 for (l = 0; l<2; l++) { /* resumption or not */
561 uint16_t cs = (uint16_t)(SupportedCipherSuites[i]);
562 KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
563 SSL_CipherAlgorithm cipher = sslCipherSuiteGetSymmetricCipherAlgorithm(cs);
564 tls_protocol_version min_version = sslCipherSuiteGetMinSupportedTLSVersion(cs);
565
566 CFArrayRef server_certs;
567
568 if(kem == SSL_ECDHE_ECDSA) {
569 server_certs = server_ec_certs;
570 } else {
571 server_certs = server_rsa_certs;
572 }
573
574
575 SKIP:{
576 bool dtls = (protos[p] == kDTLSProtocol1);
577 bool server_ok = ((kem != SSL_ECDH_ECDSA) && (kem != SSL_ECDH_RSA) && (kem != SSL_ECDH_anon));
578 bool dh_anonymous = ((kem == SSL_DH_anon) || (kem == TLS_PSK));
579 bool version_ok;
580
581 switch(protos[p]) {
582 case kDTLSProtocol1:
583 version_ok = cipher != SSL_CipherAlgorithmRC4_128 && (min_version != tls_protocol_version_TLS_1_2);
584 break;
585 case kSSLProtocol3:
586 version_ok = (min_version == tls_protocol_version_SSL_3);
587 break;
588 case kTLSProtocol1:
589 case kTLSProtocol11:
590 version_ok = (min_version != tls_protocol_version_TLS_1_2);
591 break;
592 case kTLSProtocol12:
593 version_ok = true;
594 break;
595 default:
596 version_ok = false;
597
598 }
599
600 if (!server_ok) continue;
601 if (!version_ok) continue;
602
603 int sp[2];
604 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
605 exit(errno);
606 }
607 fcntl(sp[0], F_SETNOSIGPIPE, 1);
608 fcntl(sp[1], F_SETNOSIGPIPE, 1);
609
610 ssl_test_handle *server, *client;
611 size_t num_supported_ciphers = 0;
612 SSLCipherSuite *supported_ciphers = NULL;
613
614 SSLAuthenticate client_side_auth = k;
615
616 uint32_t session_id = (p<<24) | (k<<16) | (i+1);
617 server = ssl_test_handle_create(session_id, (l == 1), true /*server*/,
618 client_side_auth, dh_anonymous, dtls,
619 sp[0], server_certs, client_certs, protos[p]);
620 client = ssl_test_handle_create(session_id, (l == 1), false /*client*/,
621 client_side_auth, dh_anonymous, dtls,
622 sp[1], client_certs, server_certs, protos[p]);
623
624 XCTAssertEqual(errSecSuccess, SSLSetPeerID(server->st, &session_id, sizeof(session_id)));
625 XCTAssertEqual(errSecSuccess, SSLSetPeerID(client->st, &session_id, sizeof(session_id)));
626
627 /* set single cipher on client, default ciphers on server */
628 num_supported_ciphers = 0;
629 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(client->st, &(SupportedCipherSuites[i]), 1));
630 XCTAssertEqual(errSecSuccess, SSLGetNumberSupportedCiphers(server->st, &num_supported_ciphers));
631 XCTAssert(supported_ciphers=malloc(num_supported_ciphers*sizeof(SSLCipherSuite)));
632 XCTAssertEqual(errSecSuccess, SSLGetSupportedCiphers(server->st, supported_ciphers, &num_supported_ciphers));
633 XCTAssertEqual(errSecSuccess, SSLSetEnabledCiphers(server->st, supported_ciphers, num_supported_ciphers));
634
635 XCTAssertEqual(errSecSuccess, SSLSetPSKSharedSecret(client->st, "123456789", 9));
636 XCTAssertEqual(errSecSuccess, SSLSetPSKSharedSecret(server->st, "123456789", 9));
637
638 pthread_create(&client_thread, NULL, securetransport_ssl_thread, client);
639 pthread_create(&server_thread, NULL, securetransport_ssl_thread, server);
640
641 intptr_t server_err, client_err;
642 pthread_join(client_thread, (void*)&client_err);
643 pthread_join(server_thread, (void*)&server_err);
644
645 #if 0
646 // If you want to print an approximate time for each handshake.
647 printf("%4llu - %40s CSA:%d RESUME:%d PROTO:0x%04x\n",
648 client->time,
649 ciphersuite_name(SupportedCipherSuites[i]),
650 server->client_side_auth,
651 l, protos[p]);
652 #endif
653
654 XCTAssert(!server_err && !client_err,
655 "%40s CSA:%d RESUME:%d PROTO:0x%04x",
656 ciphersuite_name(SupportedCipherSuites[i]),
657 server->client_side_auth,
658 l, protos[p]);
659 out:
660 free(client);
661 free(server);
662 free(supported_ciphers);
663 }
664 } /* all ciphers */
665 } /* all configs */
666
667
668 end:
669 CFReleaseSafe(client_certs);
670 CFReleaseSafe(server_ec_certs);
671 CFReleaseSafe(server_rsa_certs);
672 }
673
674 @end
675
676 /*
677 TODO: count errSSLWouldBlock
678 TODO: skip tests that don't matter: client_auth and anonymous dh
679 TODO: we seem to only be negotiating tls - force a round of sslv3
680 TODO: allow secure transport to also defer client side auth to client
681 TODO: make sure anonymous dh is never selected if not expicitly enabled
682 TODO: make sure DHE is not available if not explicitly enabled and no parameters
683 are set
684 TODO: resumable sessions
685 */