/* * sslCipher.cpp - test SSL ciphersuite protocol negotiation, client * and server side */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* default start port; caller can specify random start port */ #define STARTING_PORT 5000 #define MIN_RAND_PORT 1500 #define MAX_RAND_PORT 7000 /* * Expected errors for negotiation failure */ #define SERVER_NEGOTIATE_FAIL errSSLNegotiation #define CLIENT_NEGOTIATE_FAIL errSSLPeerHandshakeFail #define RSA_SERVER_KC "localcert" #define RSA_SERVER_ROOT "localcert.cer" #define DSA_SERVER_KC "dsacert" #define DSA_SERVER_ROOT "dsacert.cer" #define DH_PARAM_FILE_512 "dhParams_512.der" #define DH_PARAM_FILE_1024 "dhParams_1024.der" /* main() fills these in using sslKeychainPath() */ static char rsaKcPath[MAXPATHLEN]; static char dsaKcPath[MAXPATHLEN]; static void usage(char **argv) { printf("Usage: %s [options]\n", argv[0]); printf("options:\n"); printf(" q(uiet)\n"); printf(" v(erbose)\n"); printf(" p=startingPortNum\n"); printf(" t=startTestNum\n"); printf(" T=endTestNum\n"); printf(" g=startGroupNum\n"); printf(" l (large, 1024 bit Diffie-Hellman; default is 512)\n"); printf(" r(andom start port, default=%d)\n", STARTING_PORT); printf(" b (non blocking I/O)\n"); printf(" s=serverCertName; default %s\n", RSA_SERVER_ROOT); printf(" d=clientCertName; default %s\n", DSA_SERVER_ROOT); printf(" R (ringBuffer I/O)\n"); exit(1); } /* * Parameters defining one group of tests */ typedef struct { const char *groupDesc; const char *serveAcceptProts; const char *clientAcceptProts; SSLProtocol expectProt; } GroupParams; /* * Certificate parameters */ typedef struct { const char *kcName; const char *kcPassword; // last component of KC name */ const char *rootName; } CertParams; /* * Parameters defining one individual test */ typedef struct { const char *testDesc; SSLCipherSuite expectCipher; const CertParams *certParams; /* * In this test all failures are the same */ bool shouldWork; } CipherParams; /* one of three cert params */ static CertParams certRSA = { rsaKcPath, RSA_SERVER_KC, RSA_SERVER_ROOT }; static CertParams certDSA = { dsaKcPath, DSA_SERVER_KC, DSA_SERVER_ROOT }; static CertParams certNone = {NULL, NULL}; /* Note we're skipping SSL2-specific testing for simplicity's sake */ static const GroupParams sslGroupParams[] = { { "TLS1", "23t", "3t", kTLSProtocol1 }, { "SSL3", "23", "3t", kSSLProtocol3 } }; #define NUM_GROUP_PARAMS \ (sizeof(sslGroupParams) / sizeof(sslGroupParams[0])) /* some special-purpose ciphersuite arrays */ #ifdef not_used /* just SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */ static const SSLCipherSuite suites_RsaExpDh40[] = { SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_NO_SUCH_CIPHERSUITE }; #endif /* declare test name and expected cipher suite */ #define SSL_NAC(cname) #cname, cname /* * Note: the client is the only side which actually gets to * prioritize its requested CipherSuites. The server has to * go along with the first one on the client's list which the * server implements. */ const CipherParams sslCipherParams[] = { { SSL_NAC(TLS_RSA_WITH_AES_128_CBC_SHA), &certRSA, true }, { SSL_NAC(TLS_DH_DSS_WITH_AES_128_CBC_SHA), &certDSA, false }, { SSL_NAC(TLS_DH_RSA_WITH_AES_128_CBC_SHA), &certRSA, false }, { SSL_NAC(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), &certDSA, true }, { SSL_NAC(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), &certRSA, true }, { SSL_NAC(TLS_DH_anon_WITH_AES_128_CBC_SHA), &certNone, true }, { SSL_NAC(TLS_RSA_WITH_AES_256_CBC_SHA), &certRSA, true }, { SSL_NAC(TLS_DH_DSS_WITH_AES_256_CBC_SHA), &certDSA, false }, { SSL_NAC(TLS_DH_RSA_WITH_AES_256_CBC_SHA), &certRSA, false }, { SSL_NAC(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), &certDSA, true }, { SSL_NAC(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), &certRSA, true }, { SSL_NAC(TLS_DH_anon_WITH_AES_256_CBC_SHA), &certNone, true }, { SSL_NAC(SSL_RSA_EXPORT_WITH_RC4_40_MD5), &certRSA, true }, { SSL_NAC(SSL_RSA_WITH_RC4_128_MD5), &certRSA, true }, { SSL_NAC(SSL_RSA_WITH_RC4_128_SHA), &certRSA, true }, { SSL_NAC(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5), &certRSA, true }, /* skip SSL_RSA_WITH_IDEA_CBC_SHA, check later as unimpl */ { SSL_NAC(SSL_RSA_EXPORT_WITH_DES40_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_RSA_WITH_DES_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_RSA_WITH_3DES_EDE_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA), &certDSA, false }, { SSL_NAC(SSL_DH_DSS_WITH_DES_CBC_SHA), &certDSA, false }, { SSL_NAC(SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA), &certDSA, false }, { SSL_NAC(SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA), &certRSA, false }, { SSL_NAC(SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA), &certDSA, true }, { SSL_NAC(SSL_DHE_DSS_WITH_DES_CBC_SHA), &certDSA, true }, { SSL_NAC(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA), &certDSA, true }, { SSL_NAC(SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_DHE_RSA_WITH_DES_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), &certRSA, true }, { SSL_NAC(SSL_DH_anon_EXPORT_WITH_RC4_40_MD5), &certNone, true }, { SSL_NAC(SSL_DH_anon_WITH_RC4_128_MD5), &certNone, true }, { SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA), &certNone, true }, { SSL_NAC(SSL_DH_anon_WITH_DES_CBC_SHA), &certNone, true }, { SSL_NAC(SSL_DH_anon_WITH_3DES_EDE_CBC_SHA), &certNone, true }, { SSL_NAC(SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA), &certNone, true }, { SSL_NAC(SSL_FORTEZZA_DMS_WITH_NULL_SHA), &certNone, false }, { SSL_NAC(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA), &certNone, false }, }; #define NUM_CIPHER_PARAMS \ (sizeof(sslCipherParams) / sizeof(sslCipherParams[0])) #define IGNORE_SIGPIPE 1 #if IGNORE_SIGPIPE #include void sigpipe(int sig) { } #endif /* IGNORE_SIGPIPE */ /* * Default params for each test. Main() will make a copy of this and * adjust its copy on a per-test basis. */ static SslAppTestParams serverDefaults = { "no name here", false, // skipHostNameCHeck 0, // port - test must set this NULL, NULL, // RingBuffers false, // noProtSpec kSSLProtocolUnknown,// not used NULL, // acceptedProts NULL, // myCerts NULL, // password true, // idIsTrustedRoot false, // disableCertVerify NULL, // anchorFile false, // replaceAnchors kNeverAuthenticate, false, // resumeEnable NULL, // ciphers - default - server accepts all false, // nonBlocking NULL, // dhParams 0, // dhParamsLen noErr, // expectRtn kTLSProtocol1, // expectVersion kSSLClientCertNone, SSL_NULL_WITH_NULL_NULL, false, // quiet false, // silent false, // verbose {0}, // lock {0}, // cond false, // serverReady 0, // clientDone false, // serverAbort /* returned */ kSSLProtocolUnknown, SSL_NULL_WITH_NULL_NULL, kSSLClientCertNone, noHardwareErr }; SslAppTestParams clientDefaults = { "localhost", false, // skipHostNameCHeck 0, // port - test must set this NULL, NULL, // RingBuffers false, // noProtSpec kSSLProtocolUnknown,// not used NULL, // acceptedProts NULL, // myCertKcName NULL, // password true, // idIsTrustedRoot false, // disableCertVerify NULL, // anchorFile true, // replaceAnchors kNeverAuthenticate, false, // resumeEnable NULL, // ciphers - set in test loop false, // nonBlocking NULL, // dhParams 0, // dhParamsLen noErr, // expectRtn kTLSProtocol1, // expectVersion kSSLClientCertNone, SSL_NULL_WITH_NULL_NULL, false, // quiet false, // silent false, // verbose {0}, // lock {0}, // cond false, // serverReady 0, // clientDone false, // serverAbort /* returned */ kSSLProtocolUnknown, SSL_NULL_WITH_NULL_NULL, kSSLClientCertNone, noHardwareErr }; int main(int argc, char **argv) { int ourRtn = 0; char *argp; SslAppTestParams clientParams; SslAppTestParams serverParams; unsigned short portNum = STARTING_PORT; const GroupParams *groupParams; const CipherParams *cipherParams; unsigned testNum; unsigned groupNum; int thisRtn; SSLCipherSuite clientCiphers[3]; SSLCipherSuite serverCiphers[3]; RingBuffer serverToClientRing; RingBuffer clientToServerRing; bool ringBufferIo = false; /* user-spec'd variables */ unsigned startTest = 0; unsigned endTest = NUM_CIPHER_PARAMS; unsigned startGroup = 0; const char *dhParamFile = DH_PARAM_FILE_512; for(int arg=1; arggroupDesc); } for(testNum=startTest; testNumserveAcceptProts; clientParams.acceptedProts = groupParams->clientAcceptProts; serverParams.expectVersion = groupParams->expectProt; clientParams.expectVersion = groupParams->expectProt; /* per-test */ clientCiphers[0] = cipherParams->expectCipher; serverCiphers[0] = cipherParams->expectCipher; clientParams.ciphers = clientCiphers; serverParams.ciphers = serverCiphers; serverParams.expectCipher = cipherParams->expectCipher; clientParams.expectCipher = cipherParams->expectCipher; const CertParams *certParams = cipherParams->certParams; serverParams.myCertKcName = certParams->kcName; serverParams.password = certParams->kcPassword; clientParams.anchorFile = certParams->rootName; if(cipherParams->shouldWork) { serverParams.expectRtn = noErr; clientParams.expectRtn = noErr; } else { serverParams.expectRtn = SERVER_NEGOTIATE_FAIL; clientParams.expectRtn = CLIENT_NEGOTIATE_FAIL; /* server completed protocol version negotiation, * but client didn't */ clientParams.expectVersion = kSSLProtocolUnknown; } SSL_THR_RUN_NUM(serverParams, clientParams, cipherParams->testDesc, ourRtn, testNum); } } done: if(!clientParams.quiet) { if(ourRtn == 0) { printf("===== %s test PASSED =====\n", argv[0]); } else { printf("****%s FAIL: %d errors detected\n", argv[0],ourRtn); } } return ourRtn; }