1/* 2 * sslCipher.cpp - test SSL ciphersuite protocol negotiation, client 3 * and server side 4 */ 5#include <Security/SecureTransport.h> 6#include <Security/Security.h> 7#include <clAppUtils/sslAppUtils.h> 8#include <clAppUtils/ioSock.h> 9#include <clAppUtils/sslThreading.h> 10#include <security_cdsa_utils/cuFileIo.h> 11#include <utilLib/common.h> 12#include <security_cdsa_utils/cuPrintCert.h> 13#include <security_utilities/threading.h> 14#include <security_utilities/devrandom.h> 15 16#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <string.h> 21#include <time.h> 22#include <ctype.h> 23#include <sys/param.h> 24 25/* default start port; caller can specify random start port */ 26#define STARTING_PORT 5000 27 28#define MIN_RAND_PORT 1500 29#define MAX_RAND_PORT 7000 30 31/* 32 * Expected errors for negotiation failure 33 */ 34#define SERVER_NEGOTIATE_FAIL errSSLNegotiation 35#define CLIENT_NEGOTIATE_FAIL errSSLPeerHandshakeFail 36 37#define RSA_SERVER_KC "localcert" 38#define RSA_SERVER_ROOT "localcert.cer" 39#define DSA_SERVER_KC "dsacert" 40#define DSA_SERVER_ROOT "dsacert.cer" 41 42#define DH_PARAM_FILE_512 "dhParams_512.der" 43#define DH_PARAM_FILE_1024 "dhParams_1024.der" 44 45/* main() fills these in using sslKeychainPath() */ 46static char rsaKcPath[MAXPATHLEN]; 47static char dsaKcPath[MAXPATHLEN]; 48 49static void usage(char **argv) 50{ 51 printf("Usage: %s [options]\n", argv[0]); 52 printf("options:\n"); 53 printf(" q(uiet)\n"); 54 printf(" v(erbose)\n"); 55 printf(" p=startingPortNum\n"); 56 printf(" t=startTestNum\n"); 57 printf(" T=endTestNum\n"); 58 printf(" g=startGroupNum\n"); 59 printf(" l (large, 1024 bit Diffie-Hellman; default is 512)\n"); 60 printf(" r(andom start port, default=%d)\n", STARTING_PORT); 61 printf(" b (non blocking I/O)\n"); 62 printf(" s=serverCertName; default %s\n", RSA_SERVER_ROOT); 63 printf(" d=clientCertName; default %s\n", DSA_SERVER_ROOT); 64 printf(" R (ringBuffer I/O)\n"); 65 exit(1); 66} 67 68/* 69 * Parameters defining one group of tests 70 */ 71typedef struct { 72 const char *groupDesc; 73 const char *serveAcceptProts; 74 const char *clientAcceptProts; 75 SSLProtocol expectProt; 76} GroupParams; 77 78/* 79 * Certificate parameters 80 */ 81typedef struct { 82 const char *kcName; 83 const char *kcPassword; // last component of KC name */ 84 const char *rootName; 85} CertParams; 86 87/* 88 * Parameters defining one individual test 89 */ 90typedef struct { 91 const char *testDesc; 92 SSLCipherSuite expectCipher; 93 const CertParams *certParams; 94 /* 95 * In this test all failures are the same 96 */ 97 bool shouldWork; 98} CipherParams; 99 100/* one of three cert params */ 101static CertParams certRSA = { rsaKcPath, RSA_SERVER_KC, RSA_SERVER_ROOT }; 102static CertParams certDSA = { dsaKcPath, DSA_SERVER_KC, DSA_SERVER_ROOT }; 103static CertParams certNone = {NULL, NULL}; 104 105/* Note we're skipping SSL2-specific testing for simplicity's sake */ 106static const GroupParams sslGroupParams[] = 107{ 108 { "TLS1", "23t", "3t", kTLSProtocol1 }, 109 { "SSL3", "23", "3t", kSSLProtocol3 } 110}; 111#define NUM_GROUP_PARAMS \ 112 (sizeof(sslGroupParams) / sizeof(sslGroupParams[0])) 113 114/* some special-purpose ciphersuite arrays */ 115 116#ifdef not_used 117/* just SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */ 118static const SSLCipherSuite suites_RsaExpDh40[] = { 119 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, 120 SSL_NO_SUCH_CIPHERSUITE 121}; 122#endif 123 124/* declare test name and expected cipher suite */ 125#define SSL_NAC(cname) #cname, cname 126 127/* 128 * Note: the client is the only side which actually gets to 129 * prioritize its requested CipherSuites. The server has to 130 * go along with the first one on the client's list which the 131 * server implements. 132 */ 133const CipherParams sslCipherParams[] = 134{ 135 { 136 SSL_NAC(TLS_RSA_WITH_AES_128_CBC_SHA), 137 &certRSA, true 138 }, 139 { 140 SSL_NAC(TLS_DH_DSS_WITH_AES_128_CBC_SHA), 141 &certDSA, false 142 }, 143 { 144 SSL_NAC(TLS_DH_RSA_WITH_AES_128_CBC_SHA), 145 &certRSA, false 146 }, 147 { 148 SSL_NAC(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), 149 &certDSA, true 150 }, 151 { 152 SSL_NAC(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), 153 &certRSA, true 154 }, 155 { 156 SSL_NAC(TLS_DH_anon_WITH_AES_128_CBC_SHA), 157 &certNone, true 158 }, 159 { 160 SSL_NAC(TLS_RSA_WITH_AES_256_CBC_SHA), 161 &certRSA, true 162 }, 163 { 164 SSL_NAC(TLS_DH_DSS_WITH_AES_256_CBC_SHA), 165 &certDSA, false 166 }, 167 { 168 SSL_NAC(TLS_DH_RSA_WITH_AES_256_CBC_SHA), 169 &certRSA, false 170 }, 171 { 172 SSL_NAC(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), 173 &certDSA, true 174 }, 175 { 176 SSL_NAC(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), 177 &certRSA, true 178 }, 179 { 180 SSL_NAC(TLS_DH_anon_WITH_AES_256_CBC_SHA), 181 &certNone, true 182 }, 183 { 184 SSL_NAC(SSL_RSA_EXPORT_WITH_RC4_40_MD5), 185 &certRSA, true 186 }, 187 { 188 SSL_NAC(SSL_RSA_WITH_RC4_128_MD5), 189 &certRSA, true 190 }, 191 { 192 SSL_NAC(SSL_RSA_WITH_RC4_128_SHA), 193 &certRSA, true 194 }, 195 { 196 SSL_NAC(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5), 197 &certRSA, true 198 }, 199 /* skip SSL_RSA_WITH_IDEA_CBC_SHA, check later as unimpl */ 200 { 201 SSL_NAC(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA), 202 &certRSA, true 203 }, 204 { 205 SSL_NAC(SSL_RSA_WITH_DES_CBC_SHA), 206 &certRSA, true 207 }, 208 { 209 SSL_NAC(SSL_RSA_WITH_3DES_EDE_CBC_SHA), 210 &certRSA, true 211 }, 212 { 213 SSL_NAC(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA), 214 &certDSA, false 215 }, 216 { 217 SSL_NAC(SSL_DH_DSS_WITH_DES_CBC_SHA), 218 &certDSA, false 219 }, 220 { 221 SSL_NAC(SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA), 222 &certDSA, false 223 }, 224 { 225 SSL_NAC(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA), 226 &certRSA, false 227 }, 228 { 229 SSL_NAC(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA), 230 &certDSA, true 231 }, 232 { 233 SSL_NAC(SSL_DHE_DSS_WITH_DES_CBC_SHA), 234 &certDSA, true 235 }, 236 { 237 SSL_NAC(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA), 238 &certDSA, true 239 }, 240 { 241 SSL_NAC(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA), 242 &certRSA, true 243 }, 244 { 245 SSL_NAC(SSL_DHE_RSA_WITH_DES_CBC_SHA), 246 &certRSA, true 247 }, 248 { 249 SSL_NAC(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), 250 &certRSA, true 251 }, 252 { 253 SSL_NAC(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5), 254 &certNone, true 255 }, 256 { 257 SSL_NAC(SSL_DH_anon_WITH_RC4_128_MD5), 258 &certNone, true 259 }, 260 { 261 SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA), 262 &certNone, true 263 }, 264 { 265 SSL_NAC(SSL_DH_anon_WITH_DES_CBC_SHA), 266 &certNone, true 267 }, 268 { 269 SSL_NAC(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA), 270 &certNone, true 271 }, 272 { 273 SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA), 274 &certNone, true 275 }, 276 { 277 SSL_NAC(SSL_FORTEZZA_DMS_WITH_NULL_SHA), 278 &certNone, false 279 }, 280 { 281 SSL_NAC(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA), 282 &certNone, false 283 }, 284}; 285 286#define NUM_CIPHER_PARAMS \ 287 (sizeof(sslCipherParams) / sizeof(sslCipherParams[0])) 288 289#define IGNORE_SIGPIPE 1 290#if IGNORE_SIGPIPE 291#include <signal.h> 292 293void sigpipe(int sig) 294{ 295} 296#endif /* IGNORE_SIGPIPE */ 297 298/* 299 * Default params for each test. Main() will make a copy of this and 300 * adjust its copy on a per-test basis. 301 */ 302static SslAppTestParams serverDefaults = 303{ 304 "no name here", 305 false, // skipHostNameCHeck 306 0, // port - test must set this 307 NULL, NULL, // RingBuffers 308 false, // noProtSpec 309 kSSLProtocolUnknown,// not used 310 NULL, // acceptedProts 311 NULL, // myCerts 312 NULL, // password 313 true, // idIsTrustedRoot 314 false, // disableCertVerify 315 NULL, // anchorFile 316 false, // replaceAnchors 317 kNeverAuthenticate, 318 false, // resumeEnable 319 NULL, // ciphers - default - server accepts all 320 false, // nonBlocking 321 NULL, // dhParams 322 0, // dhParamsLen 323 noErr, // expectRtn 324 kTLSProtocol1, // expectVersion 325 kSSLClientCertNone, 326 SSL_NULL_WITH_NULL_NULL, 327 false, // quiet 328 false, // silent 329 false, // verbose 330 {0}, // lock 331 {0}, // cond 332 false, // serverReady 333 0, // clientDone 334 false, // serverAbort 335 /* returned */ 336 kSSLProtocolUnknown, 337 SSL_NULL_WITH_NULL_NULL, 338 kSSLClientCertNone, 339 noHardwareErr 340 341}; 342 343SslAppTestParams clientDefaults = 344{ 345 "localhost", 346 false, // skipHostNameCHeck 347 0, // port - test must set this 348 NULL, NULL, // RingBuffers 349 false, // noProtSpec 350 kSSLProtocolUnknown,// not used 351 NULL, // acceptedProts 352 NULL, // myCertKcName 353 NULL, // password 354 true, // idIsTrustedRoot 355 false, // disableCertVerify 356 NULL, // anchorFile 357 true, // replaceAnchors 358 kNeverAuthenticate, 359 false, // resumeEnable 360 NULL, // ciphers - set in test loop 361 false, // nonBlocking 362 NULL, // dhParams 363 0, // dhParamsLen 364 noErr, // expectRtn 365 kTLSProtocol1, // expectVersion 366 kSSLClientCertNone, 367 SSL_NULL_WITH_NULL_NULL, 368 false, // quiet 369 false, // silent 370 false, // verbose 371 {0}, // lock 372 {0}, // cond 373 false, // serverReady 374 0, // clientDone 375 false, // serverAbort 376 /* returned */ 377 kSSLProtocolUnknown, 378 SSL_NULL_WITH_NULL_NULL, 379 kSSLClientCertNone, 380 noHardwareErr 381}; 382 383 384int main(int argc, char **argv) 385{ 386 int ourRtn = 0; 387 char *argp; 388 SslAppTestParams clientParams; 389 SslAppTestParams serverParams; 390 unsigned short portNum = STARTING_PORT; 391 const GroupParams *groupParams; 392 const CipherParams *cipherParams; 393 unsigned testNum; 394 unsigned groupNum; 395 int thisRtn; 396 SSLCipherSuite clientCiphers[3]; 397 SSLCipherSuite serverCiphers[3]; 398 RingBuffer serverToClientRing; 399 RingBuffer clientToServerRing; 400 bool ringBufferIo = false; 401 402 /* user-spec'd variables */ 403 unsigned startTest = 0; 404 unsigned endTest = NUM_CIPHER_PARAMS; 405 unsigned startGroup = 0; 406 const char *dhParamFile = DH_PARAM_FILE_512; 407 408 for(int arg=1; arg<argc; arg++) { 409 argp = argv[arg]; 410 switch(argp[0]) { 411 case 'q': 412 serverDefaults.quiet = clientDefaults.quiet = true; 413 break; 414 case 'v': 415 serverDefaults.verbose = clientDefaults.verbose = true; 416 break; 417 case 'p': 418 portNum = atoi(&argp[2]); 419 break; 420 case 't': 421 startTest = atoi(&argp[2]); 422 break; 423 case 'T': 424 endTest = atoi(&argp[2]) + 1; 425 break; 426 case 'g': 427 startGroup = atoi(&argp[2]); 428 break; 429 case 'b': 430 serverDefaults.nonBlocking = clientDefaults.nonBlocking = 431 true; 432 break; 433 case 'l': 434 dhParamFile = DH_PARAM_FILE_1024; 435 break; 436 case 'r': 437 portNum = genRand(MIN_RAND_PORT, MAX_RAND_PORT); 438 break; 439 case 's': 440 certRSA.rootName = &argp[2]; 441 break; 442 case 'd': 443 certDSA.rootName = &argp[2]; 444 break; 445 case 'R': 446 ringBufferIo = true; 447 break; 448 default: 449 usage(argv); 450 } 451 } 452 453 if(sslCheckFile(certRSA.rootName)) { 454 exit(1); 455 } 456 if(sslCheckFile(certDSA.rootName)) { 457 exit(1); 458 } 459 if(ringBufferIo) { 460 /* set up ring buffers */ 461 ringBufSetup(&serverToClientRing, "serveToClient", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE); 462 ringBufSetup(&clientToServerRing, "clientToServe", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE); 463 serverDefaults.serverToClientRing = &serverToClientRing; 464 serverDefaults.clientToServerRing = &clientToServerRing; 465 clientDefaults.serverToClientRing = &serverToClientRing; 466 clientDefaults.clientToServerRing = &clientToServerRing; 467 } 468 469#if IGNORE_SIGPIPE 470 signal(SIGPIPE, sigpipe); 471 #endif 472 473 /* convert keychain names to paths for root */ 474 sslKeychainPath(RSA_SERVER_KC, rsaKcPath); 475 sslKeychainPath(DSA_SERVER_KC, dsaKcPath); 476 477 /* Diffie-Hellman params, we're going to need them */ 478 int r = readFile(dhParamFile, (unsigned char **)&serverDefaults.dhParams, 479 &serverDefaults.dhParamsLen); 480 if(r) { 481 printf("***Error reading diffie-hellman params from %s; aborting\n", 482 dhParamFile); 483 exit(1); 484 } 485 486 testStartBanner("sslCipher", argc, argv); 487 488 serverParams.port = portNum - 1; // gets incremented by SSL_THR_SETUP 489 490 /* 491 * To enable negotiation failures to occur, we have to pass 492 * in ciphersuite arrays which contain at least one valid 493 * ciphersuite to both client and server, but they can not 494 * be the same (or else that valid suite will be used). 495 */ 496 clientCiphers[1] = SSL_RSA_WITH_RC4_128_MD5; 497 serverCiphers[1] = SSL_RSA_WITH_RC4_128_SHA; 498 clientCiphers[2] = SSL_NO_SUCH_CIPHERSUITE; 499 serverCiphers[2] = SSL_NO_SUCH_CIPHERSUITE; 500 501 for(groupNum=startGroup; groupNum<NUM_GROUP_PARAMS; groupNum++) { 502 groupParams = &sslGroupParams[groupNum]; 503 if(!serverDefaults.quiet) { 504 printf("...%s\n", groupParams->groupDesc); 505 } 506 for(testNum=startTest; testNum<endTest; testNum++) { 507 cipherParams = &sslCipherParams[testNum]; 508 SSL_THR_SETUP(serverParams, clientParams, clientDefaults, 509 serverDefault); 510 if(ringBufferIo) { 511 ringBufferReset(&serverToClientRing); 512 ringBufferReset(&clientToServerRing); 513 } 514 /* per-group (must be after SSL_THR_SETUP) */ 515 serverParams.acceptedProts = groupParams->serveAcceptProts; 516 clientParams.acceptedProts = groupParams->clientAcceptProts; 517 serverParams.expectVersion = groupParams->expectProt; 518 clientParams.expectVersion = groupParams->expectProt; 519 520 /* per-test */ 521 clientCiphers[0] = cipherParams->expectCipher; 522 serverCiphers[0] = cipherParams->expectCipher; 523 clientParams.ciphers = clientCiphers; 524 serverParams.ciphers = serverCiphers; 525 serverParams.expectCipher = cipherParams->expectCipher; 526 clientParams.expectCipher = cipherParams->expectCipher; 527 528 const CertParams *certParams = cipherParams->certParams; 529 serverParams.myCertKcName = certParams->kcName; 530 serverParams.password = certParams->kcPassword; 531 clientParams.anchorFile = certParams->rootName; 532 533 if(cipherParams->shouldWork) { 534 serverParams.expectRtn = noErr; 535 clientParams.expectRtn = noErr; 536 } 537 else { 538 serverParams.expectRtn = SERVER_NEGOTIATE_FAIL; 539 clientParams.expectRtn = CLIENT_NEGOTIATE_FAIL; 540 541 /* server completed protocol version negotiation, 542 * but client didn't */ 543 clientParams.expectVersion = kSSLProtocolUnknown; 544 } 545 SSL_THR_RUN_NUM(serverParams, clientParams, 546 cipherParams->testDesc, ourRtn, testNum); 547 } 548 } 549 550done: 551 if(!clientParams.quiet) { 552 if(ourRtn == 0) { 553 printf("===== %s test PASSED =====\n", argv[0]); 554 } 555 else { 556 printf("****%s FAIL: %d errors detected\n", argv[0],ourRtn); 557 } 558 } 559 560 return ourRtn; 561} 562