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