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#if TARGET_OS_IPHONE
31#include <Security/SecRSAKey.h>
32#endif
33
34#include "ssl_regressions.h"
35#include "ssl-utils.h"
36
37/*
38    SSL CipherSuite tests
39
40    Below are all the ciphers that are individually tested.  The first element
41    is the SecureTransport/RFC name; the second is what openssl calls it, which
42    can be looked up in ciphers(1).
43
44    All SSL_DH_* and TLS_DH_* are disabled because neither openssl nor
45    securetranport support them:
46    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_DSS_WITH_DES_CBC_SHA,
47    SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
48    SSL_DH_RSA_WITH_DES_CBC_SHA, SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
49    TLS_DH_DSS_WITH_AES_128_CBC_SHA, TLS_DH_RSA_WITH_AES_128_CBC_SHA,
50    TLS_DH_DSS_WITH_AES_256_CBC_SHA, TLS_DH_RSA_WITH_AES_256_CBC_SHA,
51
52    DSS is unimplemented by securetransport on the phone:
53    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA,
54    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
55    TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
56
57    SSLv2 ciphersuites disabled by securetransport on phone:
58    SSL_RSA_WITH_RC2_CBC_MD5, SSL_RSA_WITH_IDEA_CBC_MD5,
59    SSL_RSA_WITH_DES_CBC_MD5, SSL_RSA_WITH_3DES_EDE_CBC_MD5,
60
61    SSLv3 ciphersuites disabled by securetransport on phone:
62    SSL_RSA_WITH_IDEA_CBC_SHA, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
63
64    Export ciphersuites disabled on iOS 5.0:
65    SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
66    SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
67    SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
68    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA
69
70*/
71
72typedef struct _CipherSuiteName {
73        SSLCipherSuite cipher;
74        const char *name;
75        bool dh_anonymous;
76} CipherSuiteName;
77
78#define CIPHER(cipher, dh_anonymous) { cipher, #cipher, dh_anonymous },
79
80static const CipherSuiteName ciphers[] = {
81    //SSL_NULL_WITH_NULL_NULL, unsupported
82    CIPHER(SSL_RSA_WITH_NULL_SHA, false)
83    CIPHER(SSL_RSA_WITH_NULL_MD5, false)
84    CIPHER(TLS_RSA_WITH_NULL_SHA256, false)
85
86    CIPHER(SSL_RSA_WITH_RC4_128_MD5, false)
87    CIPHER(SSL_RSA_WITH_RC4_128_SHA, false)
88    CIPHER(SSL_RSA_WITH_3DES_EDE_CBC_SHA, false)
89
90    CIPHER(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, false)
91    CIPHER(SSL_DH_anon_WITH_RC4_128_MD5, true)
92    CIPHER(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, true)
93    CIPHER(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, false)
94    CIPHER(TLS_DH_anon_WITH_AES_128_CBC_SHA, true)
95    CIPHER(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, false)
96    CIPHER(TLS_DH_anon_WITH_AES_256_CBC_SHA, true)
97
98    CIPHER(TLS_RSA_WITH_AES_128_CBC_SHA, false)
99    CIPHER(TLS_RSA_WITH_AES_256_CBC_SHA, false)
100
101
102    CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true)
103    CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA384, true)
104    CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA256, true)
105    CIPHER(TLS_PSK_WITH_AES_256_CBC_SHA, true)
106    CIPHER(TLS_PSK_WITH_AES_128_CBC_SHA, true)
107    CIPHER(TLS_PSK_WITH_RC4_128_SHA, true)
108    CIPHER(TLS_PSK_WITH_3DES_EDE_CBC_SHA, true)
109    CIPHER(TLS_PSK_WITH_NULL_SHA384, true)
110    CIPHER(TLS_PSK_WITH_NULL_SHA256, true)
111    CIPHER(TLS_PSK_WITH_NULL_SHA, true)
112
113
114#if 0
115    CIPHER(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, false)
116    CIPHER(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, false)
117
118    CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, false)
119    CIPHER(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, false)
120
121    CIPHER(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, false)
122    CIPHER(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, false)
123
124    CIPHER(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, true)
125    CIPHER(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, true)
126
127    CIPHER(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, false)
128    CIPHER(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, false)
129    CIPHER(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, false)
130    CIPHER(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, false)
131#endif
132
133#if 0
134    CIPHER(TLS_RSA_WITH_AES_256_GCM_SHA384, false)
135    CIPHER(TLS_RSA_WITH_AES_128_GCM_SHA256, false)
136#endif
137
138/* Export ciphers are disabled */
139#if 0
140    CIPHER(SSL_RSA_EXPORT_WITH_RC4_40_MD5, false)
141    CIPHER(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, false)
142    CIPHER(SSL_RSA_WITH_DES_CBC_SHA,  false)
143    CIPHER(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,  false)
144    CIPHER(SSL_DHE_RSA_WITH_DES_CBC_SHA, false)
145    CIPHER(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5, true)
146    CIPHER(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,  true)
147    CIPHER(SSL_DH_anon_WITH_DES_CBC_SHA, true)
148#endif
149
150    { -1 }
151};
152
153static int ciphers_len = array_size(ciphers);
154
155
156static int protos[]={kTLSProtocol1, kTLSProtocol11, kTLSProtocol12 };
157static int nprotos = sizeof(protos)/sizeof(protos[0]);
158
159
160#if 0 // currently unused
161static SSLCipherSuite sslcipher_atoi(const char *name)
162{
163       const CipherSuiteName *a = ciphers;
164       while(a->name) {
165           if (0 == strcmp(a->name, name)) break;
166           a++;
167       }
168       return a->cipher;
169}
170
171static const char * sslcipher_itoa(SSLCipherSuite num)
172{
173       const CipherSuiteName *a = ciphers;
174       while(a->cipher >= 0) {
175           if (num == a->cipher) break;
176           a++;
177       }
178       return a->name;
179}
180#endif // currently unused
181
182static unsigned char dh_param_512_bytes[] = {
183  0x30, 0x46, 0x02, 0x41, 0x00, 0xdb, 0x3c, 0xfa, 0x13, 0xa6, 0xd2, 0x64,
184  0xdf, 0xcc, 0x40, 0xb1, 0x21, 0xd4, 0xf2, 0xad, 0x22, 0x7f, 0xce, 0xa0,
185  0xb9, 0x5b, 0x95, 0x1c, 0x2e, 0x99, 0xb0, 0x27, 0xd0, 0xed, 0xf4, 0xbd,
186  0xbb, 0x36, 0x93, 0xd0, 0x9d, 0x2b, 0x32, 0xa3, 0x56, 0x53, 0xe3, 0x7b,
187  0xed, 0xa1, 0x71, 0x82, 0x2e, 0x83, 0x14, 0xf9, 0xc0, 0x2f, 0x15, 0xcb,
188  0xcf, 0x97, 0xab, 0x88, 0x49, 0x20, 0x28, 0x2e, 0x63, 0x02, 0x01, 0x02
189};
190static unsigned char *dh_param_512_der = dh_param_512_bytes;
191static unsigned int dh_param_512_der_len = 72;
192
193
194typedef struct {
195    uint32_t session_id;
196    bool is_session_resume;
197    SSLContextRef st;
198    bool is_server;
199    bool is_dtls;
200    bool client_side_auth;
201    bool dh_anonymous;
202    int comm;
203    CFArrayRef certs;
204    SSLProtocol proto;
205} ssl_test_handle;
206
207#if 0 // currently unused
208static CFArrayRef SecIdentityCopySSLClientAuthenticationChain(SecIdentityRef identity)
209{
210   CFMutableArrayRef chain = NULL;
211   SecPolicyRef policy = NULL;
212   SecTrustRef trust = NULL;
213   SecTrustResultType trust_result;
214
215   do {
216       policy = SecPolicyCreateSSL(false, NULL);
217       if (!policy)
218           break;
219
220       SecCertificateRef cert = NULL;
221       if (SecIdentityCopyCertificate(identity, &cert))
222           break;
223
224       CFArrayRef certs = CFArrayCreate(NULL, (const void **)&cert,
225                 1, &kCFTypeArrayCallBacks);
226       CFRelease(cert);
227       if (!certs)
228           break;
229
230       if (SecTrustCreateWithCertificates(certs, policy, &trust))
231           break;
232       CFRelease(certs);
233       CFRelease(policy);
234       if (SecTrustEvaluate(trust, &trust_result))
235           break;
236
237       int i, count = SecTrustGetCertificateCount(trust);
238       chain = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
239       CFArrayAppendValue(chain, identity);
240       for (i = 1; i < count; i++) {
241           if ((i+1 == count) && (trust_result == kSecTrustResultUnspecified))
242               continue; /* skip anchor if chain is complete */
243           SecCertificateRef s = SecTrustGetCertificateAtIndex(trust, i);
244           CFArrayAppendValue(chain, s);
245       }
246   } while (0);
247   if (trust)
248       CFRelease(trust);
249   if (policy)
250       CFRelease(policy);
251   return chain;
252}
253#endif // currently unused
254
255// MARK: -
256// MARK: SecureTransport support
257
258#if 0
259static void hexdump(const uint8_t *bytes, size_t len) {
260	size_t ix;
261    printf("socket write(%p, %lu)\n", bytes, len);
262	for (ix = 0; ix < len; ++ix) {
263        if (!(ix % 16))
264            printf("\n");
265		printf("%02X ", bytes[ix]);
266	}
267	printf("\n");
268}
269#else
270#define hexdump(bytes, len)
271#endif
272
273static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
274{
275	size_t len = *length;
276	uint8_t *ptr = (uint8_t *)data;
277
278    do {
279        ssize_t ret;
280        do {
281            hexdump(ptr, len);
282            ret = write((int)conn, ptr, len);
283        } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
284        if (ret > 0) {
285            len -= ret;
286            ptr += ret;
287        }
288        else
289            return -36;
290    } while (len > 0);
291
292    *length = *length - len;
293    return errSecSuccess;
294}
295
296static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
297{
298	size_t len = *length;
299	uint8_t *ptr = (uint8_t *)data;
300
301    do {
302        ssize_t ret;
303        do {
304            ret = read((int)conn, ptr, len);
305        } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
306        if (ret > 0) {
307            len -= ret;
308            ptr += ret;
309        }
310        else
311            return -36;
312    } while (len > 0);
313
314    *length = *length - len;
315    return errSecSuccess;
316}
317
318static unsigned char dn[] = {
319  0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
320  0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
321  0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e,
322  0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1d, 0x41,
323  0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
324  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
325  0x72, 0x69, 0x74, 0x79, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
326  0x03, 0x13, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74
327};
328static unsigned int dn_len = 96;
329
330static SSLContextRef make_ssl_ref(bool server, bool client_side_auth, bool dh_anonymous,
331    bool dtls, int sock, CFArrayRef certs, SSLProtocol proto)
332{
333    SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, dtls?kSSLDatagramType:kSSLStreamType);
334    require(ctx, out);
335
336    if(dtls) {
337        size_t mtu;
338        require_noerr(SSLSetMaxDatagramRecordSize(ctx, 400), out);
339        require_noerr(SSLGetMaxDatagramRecordSize(ctx, &mtu), out);
340    } else {
341        require_noerr(SSLSetProtocolVersionMax(ctx, proto), out);
342    }
343    require_noerr(SSLSetIOFuncs(ctx,
344        (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
345    require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
346    static const char *peer_domain_name = "localhost";
347    require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name,
348        strlen(peer_domain_name)), out);
349
350
351    if (!dh_anonymous) {
352        if (server)
353            require_noerr(SSLSetCertificate(ctx, certs), out);
354        if (client_side_auth && server) {
355            SSLAuthenticate auth;
356            require_noerr(SSLSetClientSideAuthenticate(ctx, kAlwaysAuthenticate), out);
357            require_noerr(SSLGetClientSideAuthenticate(ctx, &auth), out);
358            require(auth==kAlwaysAuthenticate, out);
359            require_noerr(SSLAddDistinguishedName(ctx, dn, dn_len), out);
360        }
361#if 0 /* Setting client certificate in advance */
362        if (client_side_auth && !server)
363            require_noerr(SSLSetCertificate(ctx, certs), out);
364#endif
365        if (client_side_auth && !server) /* enable break from SSLHandshake */
366            require_noerr(SSLSetSessionOption(ctx,
367                kSSLSessionOptionBreakOnCertRequested, true), out);
368        require_noerr(SSLSetSessionOption(ctx,
369            kSSLSessionOptionBreakOnServerAuth, true), out);
370    }
371
372    /* Tell SecureTransport to not check certs itself: it will break out of the
373       handshake to let us take care of it instead. */
374    require_noerr(SSLSetEnableCertVerify(ctx, false), out);
375
376    if (server) {
377        require_noerr(SSLSetDiffieHellmanParams(ctx,
378            dh_param_512_der, dh_param_512_der_len), out);
379    }
380    else /* if client */ {
381    }
382
383    return ctx;
384out:
385    if (ctx)
386        CFRelease(ctx);
387    return NULL;
388}
389
390static void *securetransport_ssl_thread(void *arg)
391{
392    OSStatus ortn;
393    ssl_test_handle * ssl = (ssl_test_handle *)arg;
394    SSLContextRef ctx = ssl->st;
395    SecTrustRef trust = NULL;
396    bool got_server_auth = false, got_client_cert_req = false;
397
398    pthread_setname_np(ssl->is_server?"server thread":"client thread");
399
400    //uint64_t start = mach_absolute_time();
401    do {
402        ortn = SSLHandshake(ctx);
403
404        if (ortn == errSSLPeerAuthCompleted)
405        {
406            require_string(!got_server_auth, out, "second server auth");
407            require_string(!got_client_cert_req, out, "got client cert req before server auth");
408            got_server_auth = true;
409            require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
410            /* verify peer cert chain */
411            require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
412            SecTrustResultType trust_result = 0;
413            /* this won't verify without setting up a trusted anchor */
414            require_noerr(SecTrustEvaluate(trust, &trust_result), out);
415
416            CFIndex n_certs = SecTrustGetCertificateCount(trust);
417            /*fprintf(stderr, "%ld certs; trust_eval: %d\n", n_certs, trust_result); */
418
419            CFMutableArrayRef peer_cert_array =
420                CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks);
421            CFMutableArrayRef orig_peer_cert_array =
422                CFArrayCreateMutableCopy(NULL, n_certs, ssl->certs);
423            while (n_certs--)
424                CFArrayInsertValueAtIndex(peer_cert_array, 0,
425                    SecTrustGetCertificateAtIndex(trust, n_certs));
426
427            SecIdentityRef ident =
428                (SecIdentityRef)CFArrayGetValueAtIndex(orig_peer_cert_array, 0);
429            SecCertificateRef peer_cert = NULL;
430            require_noerr(SecIdentityCopyCertificate(ident, &peer_cert), out);
431            CFArraySetValueAtIndex(orig_peer_cert_array, 0, peer_cert);
432            CFRelease(peer_cert);
433
434            require(CFEqual(orig_peer_cert_array, peer_cert_array), out);
435            CFRelease(orig_peer_cert_array);
436            CFRelease(peer_cert_array);
437
438            /*
439            CFStringRef cert_name = SecCertificateCopySubjectSummary(cert);
440            char cert_name_buffer[1024];
441            require(CFStringGetFileSystemRepresentation(cert_name,
442                cert_name_buffer, sizeof(cert_name_buffer)), out);
443            fprintf(stderr, "cert name: %s\n", cert_name_buffer);
444            CFRelease(trust);
445            */
446        } else if (ortn == errSSLClientCertRequested) {
447            require_string(!got_client_cert_req, out, "second client cert req");
448            require_string(got_server_auth, out, "didn't get server auth first");
449            got_client_cert_req = true;
450
451            /* set client cert */
452            require_string(!ssl->is_server, out, "errSSLClientCertRequested while running server");
453            require_string(!ssl->dh_anonymous, out, "errSSLClientCertRequested while running anon DH");
454
455            CFArrayRef DNs = NULL;
456            require_noerr(SSLCopyDistinguishedNames	(ctx, &DNs), out);
457            require(DNs, out);
458            CFRelease(DNs);
459
460            require_string(ssl->client_side_auth, out, "errSSLClientCertRequested in run not testing that");
461            require_noerr(SSLSetCertificate(ctx, ssl->certs), out);
462        }
463    } while (ortn == errSSLWouldBlock
464        || ortn == errSSLServerAuthCompleted
465        || ortn == errSSLClientCertRequested);
466    require_noerr_action_quiet(ortn, out,
467        fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
468
469    if (!ssl->is_server && !ssl->dh_anonymous && !ssl->is_session_resume) {
470        require_string(got_server_auth, out, "never got server auth");
471        if (ssl->client_side_auth)
472            require_string(got_client_cert_req, out, "never got client cert req");
473    }
474    //uint64_t elapsed = mach_absolute_time() - start;
475    //fprintf(stderr, "setr elapsed: %lld\n", elapsed);
476
477    /*
478    SSLProtocol proto = kSSLProtocolUnknown;
479    require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */
480
481    SSLCipherSuite cipherSuite;
482    require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
483    //fprintf(stderr, "st negotiated %s\n", sslcipher_itoa(cipherSuite));
484
485    if(ssl->is_dtls) {
486        size_t sz;
487        SSLGetDatagramWriteSize(ctx, &sz);
488        //fprintf(stderr, "Max Write Size = %ld\n", sz);
489    }
490
491	Boolean	sessionWasResumed = false;
492    uint8_t session_id_data[MAX_SESSION_ID_LENGTH];
493    size_t session_id_length = sizeof(session_id_data);
494    require_noerr_quiet(ortn = SSLGetResumableSessionInfo(ctx, &sessionWasResumed, session_id_data, &session_id_length), out);
495    require_action(ssl->dh_anonymous || (ssl->is_session_resume == sessionWasResumed), out, ortn = -1);
496    // if (sessionWasResumed) fprintf(stderr, "st resumed session\n");
497    //hexdump(session_id_data, session_id_length);
498
499    unsigned char ibuf[4096], obuf[4096];
500    size_t len;
501    if (ssl->is_server) {
502        SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf);
503        require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out);
504        require_action_quiet(len == sizeof(obuf), out, ortn = -1);
505    }
506    require_noerr_quiet(ortn = SSLRead(ctx, ibuf, sizeof(ibuf), &len), out);
507    require_action_quiet(len == sizeof(ibuf), out, ortn = -1);
508
509    if (ssl->is_server) {
510        require_noerr(memcmp(ibuf, obuf, sizeof(ibuf)), out);
511    } else {
512        require_noerr_quiet(ortn = SSLWrite(ctx, ibuf, sizeof(ibuf), &len), out);
513        require_action_quiet(len == sizeof(ibuf), out, ortn = -1);
514    }
515
516out:
517    SSLClose(ctx);
518    CFRelease(ctx);
519    if (trust) CFRelease(trust);
520    close(ssl->comm);
521    pthread_exit((void *)(intptr_t)ortn);
522    return NULL;
523}
524
525
526
527static ssl_test_handle *
528ssl_test_handle_create(uint32_t session_id, bool resume, bool server, bool client_side_auth, bool dh_anonymous, bool dtls,
529    int comm, CFArrayRef certs, SSLProtocol proto)
530{
531    ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
532    if (handle) {
533        handle->session_id = session_id;
534        handle->is_session_resume = resume;
535        handle->is_server = server;
536        handle->is_dtls = dtls;
537        handle->client_side_auth = client_side_auth;
538        handle->dh_anonymous = dh_anonymous;
539        handle->comm = comm;
540        handle->certs = certs;
541        handle->proto = proto;
542        handle->st = make_ssl_ref(server, client_side_auth, dh_anonymous, dtls, comm, certs, proto);
543    }
544    return handle;
545}
546
547static void
548tests(void)
549{
550    pthread_t client_thread, server_thread;
551    CFArrayRef server_certs = server_chain();
552    ok(server_certs, "got server certs");
553
554/* Enable this if you want to test a specific d/i/k/l combination */
555#if 0
556    int d=0, i=0, l=0, k=0; { {
557#else
558    int d,i,k,l,p;
559
560    for (p=0; p<nprotos; p++)
561    for (d=0;d<2; d++)  /* dtls or not dtls */
562    for (k=0; k<2; k++)
563    {
564        for (i=0; ciphers[i].cipher != (SSLCipherSuite)(-1); i++)
565        for (l = 0; l<2; l++) {
566#endif
567            SKIP:{
568                //skip("Session resumption tests do not work at this point", 1, l != 1);
569
570                int sp[2];
571                if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno);
572                fcntl(sp[0], F_SETNOSIGPIPE, 1);
573                fcntl(sp[1], F_SETNOSIGPIPE, 1);
574
575                ssl_test_handle *server, *client;
576
577                bool client_side_auth = (k);
578
579                uint32_t session_id = (k+1) << 16 | (i+1);
580                //fprintf(stderr, "session_id: %d\n", session_id);
581                server = ssl_test_handle_create(session_id, (l == 1), true /*server*/,
582                    client_side_auth, ciphers[i].dh_anonymous, d,
583                    sp[0], server_certs, protos[p]);
584                client = ssl_test_handle_create(session_id, (l == 1), false/*client*/,
585                    client_side_auth, ciphers[i].dh_anonymous, d,
586                    sp[1], server_certs, protos[p]);
587
588                require_noerr(SSLSetPeerID(server->st, &session_id, sizeof(session_id)), out);
589                require_noerr(SSLSetPeerID(client->st, &session_id, sizeof(session_id)), out);
590
591                /* set fixed cipher on client and server */
592                require_noerr(SSLSetEnabledCiphers(client->st, &ciphers[i].cipher, 1), out);
593                require_noerr(SSLSetEnabledCiphers(server->st, &ciphers[i].cipher, 1), out);
594
595                require_noerr(SSLSetPSKSharedSecret(client->st, "123456789", 9), out);
596                require_noerr(SSLSetPSKSharedSecret(server->st, "123456789", 9), out);
597
598
599                pthread_create(&client_thread, NULL, securetransport_ssl_thread, client);
600                pthread_create(&server_thread, NULL, securetransport_ssl_thread, server);
601
602                int server_err, client_err;
603                pthread_join(client_thread, (void*)&client_err);
604                pthread_join(server_thread, (void*)&server_err);
605
606
607                ok(!server_err && !client_err,
608                   "%40s ADH:%d CSA:%d DTLS:%d RESUME:%d PROTO:%d",
609                   ciphers[i].name,
610                   server->dh_anonymous,
611                   server->client_side_auth,
612                   d, l, p);
613out:
614                free(client);
615                free(server);
616
617            }
618        } /* all ciphers */
619    } /* all configs */
620
621    CFRelease(server_certs);
622}
623
624int ssl_42_ciphers(int argc, char *const *argv)
625{
626
627    plan_tests(2 * 2 * 2 * nprotos * (ciphers_len-1)/* client auth on/off * #configs * #ciphers */
628                + 1 /*cert*/);
629
630
631    tests();
632
633    return 0;
634}
635
636/*
637TODO: count errSSLWouldBlock
638TODO: skip tests that don't matter: client_auth and anonymous dh
639TODO: we seem to only be negotiating tls - force a round of sslv3
640TODO: allow secure transport to also defer client side auth to client
641TODO: make sure anonymous dh is never selected if not expicitly enabled
642TODO: make sure DHE is not available if not explicitly enabled and no parameters
643      are set
644TODO: resumable sessions
645*/
646