1/* 2 * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25 26#include <stdbool.h> 27#include <pthread.h> 28#include <fcntl.h> 29#include <sys/mman.h> 30#include <unistd.h> 31 32#include <CoreFoundation/CoreFoundation.h> 33 34#include <AssertMacros.h> 35#include <Security/SecureTransportPriv.h> /* SSLSetOption */ 36#include <Security/SecureTransport.h> 37#include <Security/SecPolicy.h> 38#include <Security/SecTrust.h> 39#include <Security/SecIdentity.h> 40#include <Security/SecIdentityPriv.h> 41#include <Security/SecCertificatePriv.h> 42#include <Security/SecKeyPriv.h> 43#include <Security/SecItem.h> 44#include <Security/SecRandom.h> 45 46#include <string.h> 47#include <sys/types.h> 48#include <sys/socket.h> 49#include <errno.h> 50#include <stdlib.h> 51#include <mach/mach_time.h> 52 53#if TARGET_OS_IPHONE 54#include <Security/SecRSAKey.h> 55#endif 56 57#include "ssl_regressions.h" 58#include "ssl-utils.h" 59 60 61typedef struct { 62 SSLContextRef st; 63 bool is_server; 64 int comm; 65 CFArrayRef certs; 66 int test; 67} ssl_test_handle; 68 69 70#pragma mark - 71#pragma mark SecureTransport support 72 73#if 0 74static void hexdump(const char *s, const uint8_t *bytes, size_t len) { 75 size_t ix; 76 printf("socket %s(%p, %lu)\n", s, bytes, len); 77 for (ix = 0; ix < len; ++ix) { 78 if (!(ix % 16)) 79 printf("\n"); 80 printf("%02X ", bytes[ix]); 81 } 82 printf("\n"); 83} 84#else 85#define hexdump(string, bytes, len) 86#endif 87 88static OSStatus SocketWrite(SSLConnectionRef h, const void *data, size_t *length) 89{ 90 int conn = ((const ssl_test_handle *)h)->comm; 91 size_t len = *length; 92 uint8_t *ptr = (uint8_t *)data; 93 94 do { 95 ssize_t ret; 96 do { 97 hexdump("write", ptr, len); 98 ret = write((int)conn, ptr, len); 99 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); 100 if (ret > 0) { 101 len -= ret; 102 ptr += ret; 103 } 104 else 105 return -36; 106 } while (len > 0); 107 108 *length = *length - len; 109 return errSecSuccess; 110} 111 112static int changepad=0; 113 114static OSStatus SocketRead(SSLConnectionRef h, void *data, size_t *length) 115{ 116 const ssl_test_handle *handle=h; 117 int conn = handle->comm; 118 size_t len = *length; 119 uint8_t *ptr = (uint8_t *)data; 120 121 122 do { 123 ssize_t ret; 124 do { 125 ret = read((int)conn, ptr, len); 126 } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); 127 if (ret > 0) { 128 len -= ret; 129 ptr += ret; 130 } 131 else 132 return -36; 133 } while (len > 0); 134 135 if(len!=0) 136 printf("Something went wrong here... len=%d\n", (int)len); 137 138 *length = *length - len; 139 140 ptr=data; 141 142 /* change pad in the data */ 143 if(changepad==1) { 144 changepad=0; 145 ptr[31]=ptr[31]^0x08^0xff; // expected padding was 8, changing it to 0xff to trigger integer underflow. 146 } 147 148 /* We are reading a data application header */ 149 if(*length==5 && ptr[0]==0x17) { 150 switch(handle->test) { 151 case 0: 152 ptr[4]=32; // reduce the size to 2 blocks and trigger integer underflow. 153 break; 154 case 1: 155 ptr[4]=48; // reduce the size to 3 blocks and triggering integer underflow in the padding. 156 break; 157 case 2: 158 changepad=1; 159 break; 160 default: 161 break; 162 } 163 } 164 165 166 return errSecSuccess; 167} 168 169 170 171static void *securetransport_ssl_thread(void *arg) 172{ 173 OSStatus ortn; 174 ssl_test_handle * ssl = (ssl_test_handle *)arg; 175 SSLContextRef ctx = ssl->st; 176 bool got_server_auth = false; 177 178 //uint64_t start = mach_absolute_time(); 179 do { 180 ortn = SSLHandshake(ctx); 181 182 if (ortn == errSSLServerAuthCompleted) 183 { 184 require_string(!got_server_auth, out, "second server auth"); 185 got_server_auth = true; 186 } 187 } while (ortn == errSSLWouldBlock 188 || ortn == errSSLServerAuthCompleted); 189 190 require_noerr_action_quiet(ortn, out, 191 fprintf(stderr, "Fell out of SSLHandshake with error: %d\n", (int)ortn)); 192 193 unsigned char ibuf[8], obuf[8]; 194 size_t len; 195 if (ssl->is_server) { 196 SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf); 197 require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out); 198 require_action_quiet(len == sizeof(obuf), out, ortn = -1); 199 } else { 200 require_noerr_quiet(ortn = SSLRead(ctx, ibuf, sizeof(ibuf), &len), out); 201 require_action_quiet(len == sizeof(ibuf), out, ortn = -1); 202 } 203 204out: 205 SSLClose(ctx); 206 CFRelease(ctx); 207 close(ssl->comm); 208 pthread_exit((void *)(intptr_t)ortn); 209 return NULL; 210} 211 212 213static ssl_test_handle * 214ssl_test_handle_create(bool server, int comm, CFArrayRef certs) 215{ 216 ssl_test_handle *handle = calloc(1, sizeof(ssl_test_handle)); 217 SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, server?kSSLServerSide:kSSLClientSide, kSSLStreamType); 218 219 require(handle, out); 220 require(ctx, out); 221 222 require_noerr(SSLSetIOFuncs(ctx, 223 (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); 224 require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)handle), out); 225 226 if (server) 227 require_noerr(SSLSetCertificate(ctx, certs), out); 228 229 require_noerr(SSLSetSessionOption(ctx, 230 kSSLSessionOptionBreakOnServerAuth, true), out); 231 232 /* Tell SecureTransport to not check certs itself: it will break out of the 233 handshake to let us take care of it instead. */ 234 require_noerr(SSLSetEnableCertVerify(ctx, false), out); 235 236 handle->is_server = server; 237 handle->comm = comm; 238 handle->certs = certs; 239 handle->st = ctx; 240 241 return handle; 242 243out: 244 if (handle) free(handle); 245 if (ctx) CFRelease(ctx); 246 return NULL; 247} 248 249static void 250tests(void) 251{ 252 pthread_t client_thread, server_thread; 253 CFArrayRef server_certs = server_chain(); 254 ok(server_certs, "got server certs"); 255 256 int i; 257 258 for(i=0; i<3; i++) 259 { 260 int sp[2]; 261 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno); 262 fcntl(sp[0], F_SETNOSIGPIPE, 1); 263 fcntl(sp[1], F_SETNOSIGPIPE, 1); 264 265 ssl_test_handle *server, *client; 266 267 server = ssl_test_handle_create(true /*server*/, sp[0], server_certs); 268 client = ssl_test_handle_create(false/*client*/, sp[1], NULL); 269 270 server->test=i; 271 client->test=i; 272 273 require(client, out); 274 require(server, out); 275 276 SSLCipherSuite cipher = TLS_RSA_WITH_AES_128_CBC_SHA256; 277 require_noerr(SSLSetEnabledCiphers(client->st, &cipher, 1), out); 278 279 pthread_create(&client_thread, NULL, securetransport_ssl_thread, client); 280 pthread_create(&server_thread, NULL, securetransport_ssl_thread, server); 281 282 int server_err, client_err; 283 pthread_join(client_thread, (void*)&client_err); 284 pthread_join(server_thread, (void*)&server_err); 285 286 287 ok(!server_err, "Server error = %d", server_err); 288 /* tests 0/1 should cause errSSLClosedAbort, 2 should cause errSSLBadRecordMac */ 289 ok(client_err==((i==2)?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %d", client_err); 290 291out: 292 free(client); 293 free(server); 294 295 } 296 CFReleaseNull(server_certs); 297} 298 299int ssl_44_crashes(int argc, char *const *argv) 300{ 301 302 plan_tests(3*2 + 1 /*cert*/); 303 304 305 tests(); 306 307 return 0; 308} 309