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