#include <Security/SecureTransport.h>
#include <Security/Security.h>
#include <clAppUtils/sslAppUtils.h>
#include <clAppUtils/ioSock.h>
#include <clAppUtils/sslThreading.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <utilLib/common.h>
#include <security_cdsa_utils/cuPrintCert.h>
#include <security_utilities/threading.h>
#include <security_utilities/devrandom.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <sys/param.h>
#define STARTING_PORT 5000
#define MIN_RAND_PORT 1500
#define MAX_RAND_PORT 7000
#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"
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);
}
typedef struct {
const char *groupDesc;
const char *serveAcceptProts;
const char *clientAcceptProts;
SSLProtocol expectProt;
} GroupParams;
typedef struct {
const char *kcName;
const char *kcPassword; const char *rootName;
} CertParams;
typedef struct {
const char *testDesc;
SSLCipherSuite expectCipher;
const CertParams *certParams;
bool shouldWork;
} CipherParams;
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};
static const GroupParams sslGroupParams[] =
{
{ "TLS1", "23t", "3t", kTLSProtocol1 },
{ "SSL3", "23", "3t", kSSLProtocol3 }
};
#define NUM_GROUP_PARAMS \
(sizeof(sslGroupParams) / sizeof(sslGroupParams[0]))
#ifdef not_used
static const SSLCipherSuite suites_RsaExpDh40[] = {
SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
SSL_NO_SUCH_CIPHERSUITE
};
#endif
#define SSL_NAC(cname) #cname, cname
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
},
{
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 <signal.h>
void sigpipe(int sig)
{
}
#endif
static SslAppTestParams serverDefaults =
{
"no name here",
false, 0, NULL, NULL, false, kSSLProtocolUnknown, NULL, NULL, NULL, true, false, NULL, false, kNeverAuthenticate,
false, NULL, false, NULL, 0, noErr, kTLSProtocol1, kSSLClientCertNone,
SSL_NULL_WITH_NULL_NULL,
false, false, false, {0}, {0}, false, 0, false,
kSSLProtocolUnknown,
SSL_NULL_WITH_NULL_NULL,
kSSLClientCertNone,
noHardwareErr
};
SslAppTestParams clientDefaults =
{
"localhost",
false, 0, NULL, NULL, false, kSSLProtocolUnknown, NULL, NULL, NULL, true, false, NULL, true, kNeverAuthenticate,
false, NULL, false, NULL, 0, noErr, kTLSProtocol1, kSSLClientCertNone,
SSL_NULL_WITH_NULL_NULL,
false, false, false, {0}, {0}, false, 0, false,
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;
unsigned startTest = 0;
unsigned endTest = NUM_CIPHER_PARAMS;
unsigned startGroup = 0;
const char *dhParamFile = DH_PARAM_FILE_512;
for(int arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'q':
serverDefaults.quiet = clientDefaults.quiet = true;
break;
case 'v':
serverDefaults.verbose = clientDefaults.verbose = true;
break;
case 'p':
portNum = atoi(&argp[2]);
break;
case 't':
startTest = atoi(&argp[2]);
break;
case 'T':
endTest = atoi(&argp[2]) + 1;
break;
case 'g':
startGroup = atoi(&argp[2]);
break;
case 'b':
serverDefaults.nonBlocking = clientDefaults.nonBlocking =
true;
break;
case 'l':
dhParamFile = DH_PARAM_FILE_1024;
break;
case 'r':
portNum = genRand(MIN_RAND_PORT, MAX_RAND_PORT);
break;
case 's':
certRSA.rootName = &argp[2];
break;
case 'd':
certDSA.rootName = &argp[2];
break;
case 'R':
ringBufferIo = true;
break;
default:
usage(argv);
}
}
if(sslCheckFile(certRSA.rootName)) {
exit(1);
}
if(sslCheckFile(certDSA.rootName)) {
exit(1);
}
if(ringBufferIo) {
ringBufSetup(&serverToClientRing, "serveToClient", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE);
ringBufSetup(&clientToServerRing, "clientToServe", DEFAULT_NUM_RB_BUFS, DEFAULT_BUF_RB_SIZE);
serverDefaults.serverToClientRing = &serverToClientRing;
serverDefaults.clientToServerRing = &clientToServerRing;
clientDefaults.serverToClientRing = &serverToClientRing;
clientDefaults.clientToServerRing = &clientToServerRing;
}
#if IGNORE_SIGPIPE
signal(SIGPIPE, sigpipe);
#endif
sslKeychainPath(RSA_SERVER_KC, rsaKcPath);
sslKeychainPath(DSA_SERVER_KC, dsaKcPath);
int r = readFile(dhParamFile, (unsigned char **)&serverDefaults.dhParams,
&serverDefaults.dhParamsLen);
if(r) {
printf("***Error reading diffie-hellman params from %s; aborting\n",
dhParamFile);
exit(1);
}
testStartBanner("sslCipher", argc, argv);
serverParams.port = portNum - 1;
clientCiphers[1] = SSL_RSA_WITH_RC4_128_MD5;
serverCiphers[1] = SSL_RSA_WITH_RC4_128_SHA;
clientCiphers[2] = SSL_NO_SUCH_CIPHERSUITE;
serverCiphers[2] = SSL_NO_SUCH_CIPHERSUITE;
for(groupNum=startGroup; groupNum<NUM_GROUP_PARAMS; groupNum++) {
groupParams = &sslGroupParams[groupNum];
if(!serverDefaults.quiet) {
printf("...%s\n", groupParams->groupDesc);
}
for(testNum=startTest; testNum<endTest; testNum++) {
cipherParams = &sslCipherParams[testNum];
SSL_THR_SETUP(serverParams, clientParams, clientDefaults,
serverDefault);
if(ringBufferIo) {
ringBufferReset(&serverToClientRing);
ringBufferReset(&clientToServerRing);
}
serverParams.acceptedProts = groupParams->serveAcceptProts;
clientParams.acceptedProts = groupParams->clientAcceptProts;
serverParams.expectVersion = groupParams->expectProt;
clientParams.expectVersion = groupParams->expectProt;
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;
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;
}