2  * sslEcdsa.cpp - test SSL connections to a number of known servers. 
   4  * Note this uses the keychain ecdsa.keychain in cwd; it contains an 
   5  * SSL client auth identity. To avoid ACL hassles and to allow this 
   6  * program to run hands-off, the identity is imported into this keychain 
   7  * with no ACL on the private key. This is done with the kcImport tool 
  10  * % kcImport ecc-secp256r1-client.pfx -k ___path_to_cwd___/ecdsa.keychain -f pkcs12 -z password -n 
  12 #include <Security/SecureTransport.h> 
  13 #include <Security/SecureTransportPriv.h> 
  14 #include <Security/Security.h> 
  15 #include "sslAppUtils.h" 
  17 //#include <utilLib/common.h> 
  19 #include <Security/SecBase.h> 
  27 #include <sys/param.h> 
  30 #include <securityd/spi.h> 
  34 static void usage(char **argv
) 
  36         printf("Usage: %s [options]\n", argv
[0]); 
  38         printf("   -t testNum   -- only do test testNum; default is all\n"); 
  39         printf("   -q           -- quiet\n"); 
  40         printf("   -b           -- non blocking I/O\n"); 
  41         printf("   -p           -- pause for malloc debug\n"); 
  45 #define IGNORE_SIGPIPE  1 
  49 static void sigpipe(int sig
) 
  52 #endif  /* IGNORE_SIGPIPE */ 
  59         /* We enable exacly one CipherSuite and require that to work */ 
  60         SSLCipherSuite                  cipherSuite
; 
  62         /* Curve to specify; SSL_Curve_None means use default */ 
  63         SSL_ECDSA_NamedCurve    specCurve
; 
  65         /* Curve to verify; SSL_Curve_None means don't check */ 
  66         SSL_ECDSA_NamedCurve    expCurve
; 
  69          * keychain containing client-side cert, located in LOCAL_BUILD_DIR. 
  70          * NULL means no keychain. 
  74         /* password for above keychain */ 
  75         const char                              *kcPassword
; 
  78 static const EcdsaTestParams ecdsaTestParams
[] = 
  82                 "tls.secg.org", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
  83                 SSL_Curve_None
, SSL_Curve_None
, 
  84                 "ecdsa.keychain", "password" 
  86         /* tla.secg.org -- port 40023 - secp256r1  */ 
  88                 "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
, 
  89                 SSL_Curve_None
, SSL_Curve_secp256r1
 
  92                 "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
, 
  93                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
  96                 "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
  97                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 100                 "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
, 
 101                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 104                 "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 105                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 108                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 109                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 112                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 113                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 116                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 117                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 120                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_RC4_128_SHA
, 
 121                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 124                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 125                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 128                 "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 129                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 132         /* tla.secg.org -- port 40024 - secp384r1 */ 
 133         /* This one doesn't let you specify a curve */ 
 135                 "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
, 
 136                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 139                 "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
 140                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 143                 "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
, 
 144                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 147                 "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 148                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 151                 "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 152                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 155                 "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 156                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 159                 "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_RC4_128_SHA
, 
 160                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 163                 "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 164                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 167         /* tla.secg.org -- port 40025 - secp521r1 */ 
 169                 "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
, 
 170                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 173                 "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
 174                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 177                 "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
, 
 178                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 181                 "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 182                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 185                 "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 186                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 189                 "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 190                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 193                 "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_RC4_128_SHA
, 
 194                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 197                 "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 198                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 202         /* ecc.fedora.redhat.com - port 8443 - secp256r1 */ 
 204                 "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
, 
 205                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 208                 "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
 209                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 212                 "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
, 
 213                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 216                 "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 217                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 220                 "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 221                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 224                 "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 225                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 228                 "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_RC4_128_SHA
, 
 229                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 232                 "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 233                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 236         /* ecc.fedora.redhat.com - port 8444 - SSL_Curve_secp384r1 */ 
 237         /* This doesn't work, the server requires a redirect ... 
 239                 "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 
 240                 SSL_Curve_None, SSL_Curve_secp384r1 
 244                 "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
 245                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 248                 "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
, 
 249                 SSL_Curve_secp384r1
, SSL_Curve_secp384r1
 
 252                 "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 253                 SSL_Curve_secp384r1
, SSL_Curve_secp384r1
 
 256                 "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 257                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 260                 "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
, 
 261                 SSL_Curve_None
, SSL_Curve_secp384r1
 
 264                 "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_RC4_128_SHA
, 
 265                 SSL_Curve_secp384r1
, SSL_Curve_secp384r1
 
 268                 "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
, 
 269                 SSL_Curve_secp384r1
, SSL_Curve_secp384r1
 
 272         /* ecc.fedora.redhat.com - port 8445 - SSL_Curve_secp521r1 */ 
 273         /* This one can't do RC4_128 without some HTTP redirection */ 
 275                 "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 276                 SSL_Curve_None
, SSL_Curve_secp521r1
 
 279                 "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
, 
 280                 SSL_Curve_secp521r1
, SSL_Curve_secp521r1
 
 283                 "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
, 
 284                 SSL_Curve_secp521r1
, SSL_Curve_secp521r1
 
 287         /* ecc.fedora.redhat.com - port 443 - secp256r1 with RSA authentication */ 
 289                 "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
, 
 290                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 293                 "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
, 
 294                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 297                 "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_RC4_128_SHA
, 
 298                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 301                 "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
, 
 302                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 305                 "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
, 
 306                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 309                 "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
, 
 310                 SSL_Curve_secp256r1
, SSL_Curve_secp256r1
 
 313                 "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_RC4_128_SHA
, 
 314                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 317                 "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
, 
 318                 SSL_Curve_None
, SSL_Curve_secp256r1
 
 323 #define NUM_TEST_PARAMS         (sizeof(ecdsaTestParams) / sizeof(ecdsaTestParams[0])) 
 325 static void dumpParams( 
 326         const EcdsaTestParams 
*testParams
) 
 328         printf("%s:%d %-33s ", 
 329                 testParams
->hostName
, testParams
->port
, 
 330                 /* skip leading "TLS_" */ 
 331                 sslGetCipherSuiteString(testParams
->cipherSuite
)+4); 
 332         if(testParams
->expCurve 
!= SSL_Curve_None
) { 
 333                 printf("expCurve = %s ", sslCurveString(testParams
->expCurve
)); 
 335         if(testParams
->specCurve 
!= SSL_Curve_None
) { 
 336                 printf("specCurve = %s ", sslCurveString(testParams
->specCurve
)); 
 338         if(testParams
->keychain
) { 
 339                 printf("Client Auth Enabled"); 
 344 static void dumpErrInfo( 
 346         const EcdsaTestParams 
*testParams
, 
 349         printf("***%s failed for ", op
); 
 350         dumpParams(testParams
); 
 351         printf("   error: %s\n", sslGetSSLErrString(ortn
)); 
 355  * Custom ping for this test. 
 357 #define RCV_BUF_SIZE            256 
 359 static int doSslPing( 
 360         const EcdsaTestParams   
*testParams
, 
 367     SSLContextRef       ctx 
= NULL
; 
 368         SSLCipherSuite          negCipher
; 
 370         /* first make sure requested server is there */ 
 371         ortn 
= MakeServerConnection(testParams
->hostName
, testParams
->port
, 
 372                 nonBlocking
, &sock
, &peerId
); 
 374         printf("MakeServerConnection(%s) returned %d\n", 
 375                         testParams
->hostName
, (int)ortn
); 
 380          * Set up a SecureTransport session. 
 381          * First the standard calls. 
 383 #pragma clang diagnostic push 
 384 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 
 385         ortn 
= SSLNewContext(false, &ctx
); 
 387                 printSslErrStr("SSLNewContext", ortn
); 
 390         ortn 
= SSLSetIOFuncs(ctx
, SocketRead
, SocketWrite
); 
 392                 printSslErrStr("SSLSetIOFuncs", ortn
); 
 396         /* Restrict to only TLSv1 - we have to do this because of Radar 6133465 */ 
 397         ortn 
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false); 
 399                 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
); 
 402         ortn 
= SSLSetProtocolVersionEnabled(ctx
, kTLSProtocol1
, true); 
 404                 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
); 
 408         /* Restrict to only one CipherSuite */ 
 409         ortn 
= SSLSetEnabledCiphers(ctx
, &testParams
->cipherSuite
, 1); 
 411                 printSslErrStr("SSLSetEnabledCiphers", ortn
); 
 415         ortn 
= SSLSetConnection(ctx
, (SSLConnectionRef
)(intptr_t)sock
); 
 417                 printSslErrStr("SSLSetConnection", ortn
); 
 421         /* These test servers have custom roots, just allow any roots for this test */ 
 422         ortn 
= SSLSetAllowsExpiredCerts(ctx
, true); 
 424                 printSslErrStr("SSLSetAllowExpiredCerts", ortn
); 
 427         ortn 
= SSLSetAllowsAnyRoot(ctx
, true); 
 429                 printSslErrStr("SSLSetAllowAnyRoot", ortn
); 
 433         if(testParams
->specCurve 
!= SSL_Curve_None
) { 
 434                 ortn 
= SSLSetECDSACurves(ctx
, &testParams
->specCurve
, 1); 
 436                         printSslErrStr("SSLSetAllowAnyRoot", ortn
); 
 442                 ortn 
= SSLHandshake(ctx
); 
 443     } while (ortn 
== errSSLWouldBlock
); 
 445     /* convert normal "shutdown" into zero err rtn */ 
 449                 case errSSLClosedGraceful
: 
 450                 case errSSLClosedNoNotify
: 
 451                         ortn 
= errSecSuccess
; 
 454                         dumpErrInfo("SSLHandshake", testParams
, ortn
); 
 460          * Unlike other ping tests we don't bother with a GET - just validate 
 463         ortn 
= SSLGetNegotiatedCipher(ctx
, &negCipher
); 
 465                 dumpErrInfo("SSLHandshake", testParams
, ortn
); 
 469         /* here is really what we're testing */ 
 470         if(negCipher 
!= testParams
->cipherSuite
) { 
 471                 printf("***Cipher mismatch for "); 
 472                 dumpParams(testParams
); 
 473                 printf("Negotiated cipher: %s\n", sslGetCipherSuiteString(negCipher
)); 
 477         if(testParams
->expCurve 
!= SSL_Curve_None
) { 
 478                 SSL_ECDSA_NamedCurve actNegCurve
; 
 479                 ortn 
= SSLGetNegotiatedCurve(ctx
, &actNegCurve
); 
 481                         printSslErrStr("SSLGetNegotiatedCurve", ortn
); 
 484                 if(actNegCurve 
!= testParams
->expCurve
) { 
 485                         printf("***Negotiated curve error\n"); 
 486                         printf("Specified curve: %s\n", sslCurveString(testParams
->specCurve
)); 
 487                         printf("Expected  curve: %s\n", sslCurveString(testParams
->expCurve
)); 
 488                         printf("Obtained  curve: %s\n", sslCurveString(actNegCurve
)); 
 493         if(testParams
->keychain
) { 
 494                 /* Verify client auth */ 
 495                 SSLClientCertificateState authState
; 
 496                 ortn 
= SSLGetClientCertificateState(ctx
, &authState
); 
 498                         printSslErrStr("SSLGetClientCertificateState", ortn
); 
 501                 if(authState 
!= kSSLClientCertSent
) { 
 502                         printf("***Unexpected ClientCertificateState\n"); 
 503                         printf("   Expected: ClientCertSent\n"); 
 504                         printf("   Received: %s\n", sslGetClientCertStateString(authState
)); 
 510     ortn 
= SSLClose(ctx
); 
 512 #pragma clang diagnostic pop 
 516                 endpointShutdown(sock
); 
 519             SSLDisposeContext(ctx
); 
 525 int main(int argc
, char **argv
) 
 529         int                     nonBlocking 
= false; 
 531         unsigned        maxDex 
= NUM_TEST_PARAMS
-1; 
 532         bool            doPause 
= false; 
 536         while ((arg 
= getopt(argc
, argv
, "t:bpqh")) != -1) { 
 539                                 minDex 
= maxDex 
= atoi(optarg
); 
 540                                 if(minDex 
> (NUM_TEST_PARAMS 
- 1)) { 
 541                                         printf("***max test number is %u.\n", (unsigned)NUM_TEST_PARAMS
); 
 564     securityd_init(NULL
); 
 569         signal(SIGPIPE
, sigpipe
); 
 572         //testStartBanner("sslEcdsa", argc, argv); 
 576                 printf("Pausing at top of loop; CR to continue: "); 
 581         for(unsigned dex
=minDex
; dex
<=maxDex
; dex
++) { 
 582                 const EcdsaTestParams 
*testParams 
= &ecdsaTestParams
[dex
]; 
 584                         printf("[%u]: ", dex
); 
 585                         dumpParams(testParams
); 
 587                 ourRtn 
= doSslPing(testParams
, quiet
, nonBlocking
); 
 589             //printf("** Test %u failed **\n", dex); 
 590                         //if(testError(quiet)) { 
 598                 printf("Pausing at end of loop; CR to continue: "); 
 605                         printf("===== sslEcdsa test PASSED =====\n"); 
 608                         printf("****sslEcdsa test FAILED\n");