]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/regressions/ssl-45-tls12.c
Security-55471.14.tar.gz
[apple/security.git] / libsecurity_ssl / regressions / ssl-45-tls12.c
1 //
2 // ssl-43-ciphers.c
3 // regressions
4 //
5 // Created by Fabrice Gautier on 6/7/11.
6 // Copyright 2011 Apple, Inc. All rights reserved.
7 //
8
9 #include <stdbool.h>
10 #include <pthread.h>
11 #include <fcntl.h>
12 #include <sys/mman.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <sys/socket.h>
17 #include <netdb.h>
18 #include <arpa/inet.h>
19 #include <CoreFoundation/CoreFoundation.h>
20
21 #include <AssertMacros.h>
22 #include <Security/SecureTransportPriv.h> /* SSLSetOption */
23 #include <Security/SecureTransport.h>
24 #include <Security/SecPolicy.h>
25 #include <Security/SecTrust.h>
26 #include <Security/SecIdentity.h>
27 #include <Security/SecIdentityPriv.h>
28 #include <Security/SecCertificatePriv.h>
29 #include <Security/SecKeyPriv.h>
30 #include <Security/SecItem.h>
31 #include <Security/SecRandom.h>
32
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <mach/mach_time.h>
39
40 #include "ssl_regressions.h"
41
42 typedef struct {
43 uint32_t session_id;
44 bool is_session_resume;
45 SSLContextRef st;
46 bool is_server;
47 bool client_side_auth;
48 bool dh_anonymous;
49 int comm;
50 CFArrayRef certs;
51 } ssl_test_handle;
52
53
54
55 #if 0
56 static void hexdump(const uint8_t *bytes, size_t len) {
57 size_t ix;
58 printf("socket write(%p, %lu)\n", bytes, len);
59 for (ix = 0; ix < len; ++ix) {
60 if (!(ix % 16))
61 printf("\n");
62 printf("%02X ", bytes[ix]);
63 }
64 printf("\n");
65 }
66 #else
67 #define hexdump(bytes, len)
68 #endif
69
70 static int SocketConnect(const char *hostName, int port)
71 {
72 struct sockaddr_in addr;
73 struct in_addr host;
74 int sock;
75 int err;
76 struct hostent *ent;
77
78 if (hostName[0] >= '0' && hostName[0] <= '9')
79 {
80 host.s_addr = inet_addr(hostName);
81 }
82 else {
83 unsigned dex;
84 #define GETHOST_RETRIES 5
85 /* seeing a lot of soft failures here that I really don't want to track down */
86 for(dex=0; dex<GETHOST_RETRIES; dex++) {
87 if(dex != 0) {
88 printf("\n...retrying gethostbyname(%s)", hostName);
89 }
90 ent = gethostbyname(hostName);
91 if(ent != NULL) {
92 break;
93 }
94 }
95 if(ent == NULL) {
96 printf("\n***gethostbyname(%s) returned: %s\n", hostName, hstrerror(h_errno));
97 return -1;
98 }
99 memcpy(&host, ent->h_addr, sizeof(struct in_addr));
100 }
101
102
103 sock = socket(AF_INET, SOCK_STREAM, 0);
104 addr.sin_addr = host;
105 addr.sin_port = htons((u_short)port);
106
107 addr.sin_family = AF_INET;
108 err = connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in));
109
110 if(err!=0)
111 {
112 perror("connect failed");
113 return err;
114 }
115
116 return sock;
117 }
118
119
120 static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length)
121 {
122 size_t len = *length;
123 uint8_t *ptr = (uint8_t *)data;
124
125 do {
126 ssize_t ret;
127 do {
128 hexdump(ptr, len);
129 ret = write((int)conn, ptr, len);
130 if (ret < 0)
131 perror("send");
132 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
133 if (ret > 0) {
134 len -= ret;
135 ptr += ret;
136 }
137 else
138 return -36;
139 } while (len > 0);
140
141 *length = *length - len;
142 return errSecSuccess;
143 }
144
145 static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length)
146 {
147 size_t len = *length;
148 uint8_t *ptr = (uint8_t *)data;
149
150 do {
151 ssize_t ret;
152 do {
153 ret = read((int)conn, ptr, len);
154 if (ret < 0)
155 perror("send");
156 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR));
157 if (ret > 0) {
158 len -= ret;
159 ptr += ret;
160 }
161 else
162 return -36;
163 } while (len > 0);
164
165 *length = *length - len;
166 return errSecSuccess;
167 }
168
169 static SSLContextRef make_ssl_ref(int sock, SSLProtocol maxprot)
170 {
171 SSLContextRef ctx = NULL;
172
173 require_noerr(SSLNewContext(false, &ctx), out);
174 require_noerr(SSLSetIOFuncs(ctx,
175 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out);
176 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock), out);
177
178 require_noerr(SSLSetSessionOption(ctx,
179 kSSLSessionOptionBreakOnServerAuth, true), out);
180
181 require_noerr(SSLSetProtocolVersionMax(ctx, maxprot), out);
182 /* Tell SecureTransport to not check certs itself: it will break out of the
183 handshake to let us take care of it instead. */
184 require_noerr(SSLSetEnableCertVerify(ctx, false), out);
185
186 return ctx;
187 out:
188 if (ctx)
189 SSLDisposeContext(ctx);
190 return NULL;
191 }
192
193 static OSStatus securetransport(ssl_test_handle * ssl)
194 {
195 OSStatus ortn;
196 SSLContextRef ctx = ssl->st;
197 SecTrustRef trust = NULL;
198 bool got_server_auth = false, got_client_cert_req = false;
199
200 //uint64_t start = mach_absolute_time();
201 do {
202 ortn = SSLHandshake(ctx);
203
204 if (ortn == errSSLServerAuthCompleted)
205 {
206 require_string(!got_server_auth, out, "second server auth");
207 require_string(!got_client_cert_req, out, "got client cert req before server auth");
208 got_server_auth = true;
209 require_string(!trust, out, "Got errSSLServerAuthCompleted twice?");
210 /* verify peer cert chain */
211 require_noerr(SSLCopyPeerTrust(ctx, &trust), out);
212 SecTrustResultType trust_result = 0;
213 /* this won't verify without setting up a trusted anchor */
214 require_noerr(SecTrustEvaluate(trust, &trust_result), out);
215
216 } } while (ortn == errSSLWouldBlock
217 || ortn == errSSLServerAuthCompleted);
218 require_noerr_action_quiet(ortn, out,
219 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn));
220
221 require_string(got_server_auth, out, "never got server auth");
222
223 //uint64_t elapsed = mach_absolute_time() - start;
224 //fprintf(stderr, "setr elapsed: %lld\n", elapsed);
225
226 /*
227 SSLProtocol proto = kSSLProtocolUnknown;
228 require_noerr_quiet(SSLGetNegotiatedProtocolVersion(ctx, &proto), out); */
229
230 SSLCipherSuite cipherSuite;
231 require_noerr_quiet(ortn = SSLGetNegotiatedCipher(ctx, &cipherSuite), out);
232 //fprintf(stderr, "st negotiated %02x\n", cipherSuite);
233
234
235 out:
236 SSLClose(ctx);
237 SSLDisposeContext(ctx);
238 if (trust) CFRelease(trust);
239
240 return ortn;
241 }
242
243
244
245 static ssl_test_handle *
246 ssl_test_handle_create(int comm, SSLProtocol maxprot)
247 {
248 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle));
249 if (handle) {
250 handle->comm = comm;
251 handle->st = make_ssl_ref(comm, maxprot);
252 }
253 return handle;
254 }
255
256
257 struct s_server {
258 char *host;
259 int port;
260 SSLProtocol maxprot;
261 } servers[] = {
262 /* Good tls 1.2 servers */
263 {"encrypted.google.com", 443, kTLSProtocol12 },
264 {"www.amazon.com",443, kTLSProtocol12 },
265 {"www.mikestoolbox.org",443, kTLSProtocol12 },
266 /* servers with issues */
267 {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version
268 {"imap.softbank.jp",993, kTLSProtocol1 }, // softbank imap server, there are multiple servers behind this, one of them is not able to handle downgrading to TLS 1.2 properly (126.240.66.17).
269 {"mobile.charter.net",993, kTLSProtocol1 }, // Support 1.2 but fail to negotiate properly
270 {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */
271 };
272
273 #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0]))
274 #define NLOOPS 1
275
276 static void
277 tests(void)
278 {
279 int p;
280
281 for(p=0; p<NSERVERS;p++) {
282 for(int loops=0; loops<NLOOPS; loops++) {
283
284 ssl_test_handle *client;
285
286 int s;
287 OSStatus r;
288
289 s=SocketConnect(servers[p].host, servers[p].port);
290 if(s<0) {
291 fail("connect failed with err=%d - %s:%d (try %d)", s, servers[p].host, servers[p].port, loops);
292 break;
293 }
294
295 client = ssl_test_handle_create(s, servers[p].maxprot);
296
297 r=securetransport(client);
298 ok(!r, "handshake failed with err=%ld - %s:%d (try %d)", (long)r, servers[p].host, servers[p].port, loops);
299
300 close(s);
301 } }
302 }
303
304 int ssl_45_tls12(int argc, char *const *argv)
305 {
306 plan_tests(NSERVERS*NLOOPS);
307
308 tests();
309
310 return 0;
311 }