]> git.saurik.com Git - apple/security.git/blobdiff - sslViewer/sslEcdsa.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / sslViewer / sslEcdsa.cpp
diff --git a/sslViewer/sslEcdsa.cpp b/sslViewer/sslEcdsa.cpp
new file mode 100644 (file)
index 0000000..1ac4939
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * sslEcdsa.cpp - test SSL connections to a number of known servers.
+ *
+ * Note this uses the keychain ecdsa.keychain in cwd; it contains an
+ * SSL client auth identity. To avoid ACL hassles and to allow this
+ * program to run hands-off, the identity is imported into this keychain
+ * with no ACL on the private key. This is done with the kcImport tool
+ * like so:
+ *
+ * % kcImport ecc-secp256r1-client.pfx -k ___path_to_cwd___/ecdsa.keychain -f pkcs12 -z password -n
+ */
+#include <Security/SecureTransport.h>
+#include <Security/SecureTransportPriv.h>
+#include <Security/Security.h>
+#include "sslAppUtils.h"
+#include "ioSock.h"
+//#include <utilLib/common.h>
+
+#include <Security/SecBase.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/param.h>
+
+#if NO_SERVER
+#include <securityd/spi.h>
+#endif
+
+
+static void usage(char **argv)
+{
+       printf("Usage: %s [options]\n", argv[0]);
+       printf("options:\n");
+       printf("   -t testNum   -- only do test testNum; default is all\n");
+       printf("   -q           -- quiet\n");
+       printf("   -b           -- non blocking I/O\n");
+       printf("   -p           -- pause for malloc debug\n");
+       exit(1);
+}
+
+#define IGNORE_SIGPIPE 1
+#if    IGNORE_SIGPIPE
+#include <signal.h>
+
+static void sigpipe(int sig)
+{
+}
+#endif /* IGNORE_SIGPIPE */
+
+/* Test params */
+typedef struct {
+       const char                              *hostName;
+       int                                             port;
+
+       /* We enable exacly one CipherSuite and require that to work */
+       SSLCipherSuite                  cipherSuite;
+
+       /* Curve to specify; SSL_Curve_None means use default */
+       SSL_ECDSA_NamedCurve    specCurve;
+
+       /* Curve to verify; SSL_Curve_None means don't check */
+       SSL_ECDSA_NamedCurve    expCurve;
+
+       /*
+        * keychain containing client-side cert, located in LOCAL_BUILD_DIR.
+        * NULL means no keychain.
+        */
+       const char                              *keychain;
+
+       /* password for above keychain */
+       const char                              *kcPassword;
+} EcdsaTestParams;
+
+static const EcdsaTestParams ecdsaTestParams[] =
+{
+       /* client auth */
+       {
+               "tls.secg.org", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_None,
+               "ecdsa.keychain", "password"
+       },
+       /* tla.secg.org -- port 40023 - secp256r1  */
+       {
+               "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "tls.secg.org", 40023, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+
+       /* tla.secg.org -- port 40024 - secp384r1 */
+       /* This one doesn't let you specify a curve */
+       {
+               "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "tls.secg.org", 40024, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+
+       /* tla.secg.org -- port 40025 - secp521r1 */
+       {
+               "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "tls.secg.org", 40025, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+
+
+       /* ecc.fedora.redhat.com - port 8443 - secp256r1 */
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8443, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+
+       /* ecc.fedora.redhat.com - port 8444 - SSL_Curve_secp384r1 */
+       /* This doesn't work, the server requires a redirect ...
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       */
+       {
+               "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_secp384r1, SSL_Curve_secp384r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp384r1, SSL_Curve_secp384r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp384r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+               SSL_Curve_secp384r1, SSL_Curve_secp384r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8444, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp384r1, SSL_Curve_secp384r1
+       },
+
+       /* ecc.fedora.redhat.com - port 8445 - SSL_Curve_secp521r1 */
+       /* This one can't do RC4_128 without some HTTP redirection */
+       {
+               "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp521r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8445, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_secp521r1, SSL_Curve_secp521r1
+       },
+       {
+               "ecc.fedora.redhat.com", 8445, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_secp521r1, SSL_Curve_secp521r1
+       },
+
+       /* ecc.fedora.redhat.com - port 443 - secp256r1 with RSA authentication */
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+               SSL_Curve_secp256r1, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_RC4_128_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+       {
+               "ecc.fedora.redhat.com", 443, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+               SSL_Curve_None, SSL_Curve_secp256r1
+       },
+
+       /* etc. */
+};
+#define NUM_TEST_PARAMS                (sizeof(ecdsaTestParams) / sizeof(ecdsaTestParams[0]))
+
+static void dumpParams(
+       const EcdsaTestParams *testParams)
+{
+       printf("%s:%d %-33s ",
+               testParams->hostName, testParams->port,
+               /* skip leading "TLS_" */
+               sslGetCipherSuiteString(testParams->cipherSuite)+4);
+       if(testParams->expCurve != SSL_Curve_None) {
+               printf("expCurve = %s ", sslCurveString(testParams->expCurve));
+       }
+       if(testParams->specCurve != SSL_Curve_None) {
+               printf("specCurve = %s ", sslCurveString(testParams->specCurve));
+       }
+       if(testParams->keychain) {
+               printf("Client Auth Enabled");
+       }
+       putchar('\n');
+}
+
+static void dumpErrInfo(
+       const char *op,
+       const EcdsaTestParams *testParams,
+       OSStatus ortn)
+{
+       printf("***%s failed for ", op);
+       dumpParams(testParams);
+       printf("   error: %s\n", sslGetSSLErrString(ortn));
+}
+
+/*
+ * Custom ping for this test.
+ */
+#define RCV_BUF_SIZE           256
+
+static int doSslPing(
+       const EcdsaTestParams   *testParams,
+       bool                                    quiet,
+       int                                             nonBlocking)
+{
+    PeerSpec            peerId;
+       otSocket                        sock = 0;
+    OSStatus            ortn;
+    SSLContextRef       ctx = NULL;
+       SSLCipherSuite          negCipher;
+
+       /* first make sure requested server is there */
+       ortn = MakeServerConnection(testParams->hostName, testParams->port,
+               nonBlocking, &sock, &peerId);
+    if(ortn) {
+       printf("MakeServerConnection(%s) returned %d\n",
+                       testParams->hostName, (int)ortn);
+       return -1;
+    }
+
+       /*
+        * Set up a SecureTransport session.
+        * First the standard calls.
+        */
+       ortn = SSLNewContext(false, &ctx);
+       if(ortn) {
+               printSslErrStr("SSLNewContext", ortn);
+               goto cleanup;
+       }
+       ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite);
+       if(ortn) {
+               printSslErrStr("SSLSetIOFuncs", ortn);
+               goto cleanup;
+       }
+
+       /* Restrict to only TLSv1 - we have to do this because of Radar 6133465 */
+       ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
+       if(ortn) {
+               printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
+               goto cleanup;
+       }
+       ortn = SSLSetProtocolVersionEnabled(ctx, kTLSProtocol1, true);
+       if(ortn) {
+               printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
+               goto cleanup;
+       }
+
+       /* Restrict to only one CipherSuite */
+       ortn = SSLSetEnabledCiphers(ctx, &testParams->cipherSuite, 1);
+       if(ortn) {
+               printSslErrStr("SSLSetEnabledCiphers", ortn);
+               goto cleanup;
+       }
+
+       ortn = SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)sock);
+       if(ortn) {
+               printSslErrStr("SSLSetConnection", ortn);
+               goto cleanup;
+       }
+
+       /* These test servers have custom roots, just allow any roots for this test */
+       ortn = SSLSetAllowsExpiredCerts(ctx, true);
+       if(ortn) {
+               printSslErrStr("SSLSetAllowExpiredCerts", ortn);
+               goto cleanup;
+       }
+       ortn = SSLSetAllowsAnyRoot(ctx, true);
+       if(ortn) {
+               printSslErrStr("SSLSetAllowAnyRoot", ortn);
+               goto cleanup;
+       }
+
+       if(testParams->specCurve != SSL_Curve_None) {
+               ortn = SSLSetECDSACurves(ctx, &testParams->specCurve, 1);
+               if(ortn) {
+                       printSslErrStr("SSLSetAllowAnyRoot", ortn);
+                       goto cleanup;
+               }
+       }
+
+#if 0
+       if(testParams->keychain) {
+               char kcPath[2000];
+               const char *lbd = getenv("LOCAL_BUILD_DIR");
+               if(lbd == NULL) {
+                       printf("WARNING: no LOCAL_BUILD_DIR env var faound\n");
+                       lbd = "";
+               }
+               snprintf(kcPath, 2000, "%s/%s", lbd, testParams->keychain);
+               SecKeychainRef kcRef = NULL;
+               CFArrayRef certArray = getSslCerts(kcPath,
+                       false,          // encryptOnly
+                       false,          // completeCertChain
+                       NULL,                   // anchorFile
+                       &kcRef);
+               if(kcRef) {
+                       /* Unlock it */
+                       ortn = SecKeychainUnlock(kcRef,
+                               strlen(testParams->kcPassword), testParams->kcPassword,
+                               true);
+                       if(ortn) {
+                               cssmPerror("SecKeychainUnlock", ortn);
+                               /* oh well */
+                       }
+                       CFRelease(kcRef);
+               }
+               if(certArray == NULL) {
+                       printf("***WARNING no keychain found at %s\n", kcPath);
+               }
+               ortn = SSLSetCertificate(ctx, certArray);
+               if(ortn) {
+                       printSslErrStr("SSLSetAllowAnyRoot", ortn);
+                       goto cleanup;
+               }
+               CFRelease(certArray);
+       }
+#endif
+    do {
+               ortn = SSLHandshake(ctx);
+    } while (ortn == errSSLWouldBlock);
+
+    /* convert normal "shutdown" into zero err rtn */
+       switch(ortn) {
+               case errSecSuccess:
+                       break;
+               case errSSLClosedGraceful:
+               case errSSLClosedNoNotify:
+                       ortn = errSecSuccess;
+                       goto cleanup;
+               default:
+                       dumpErrInfo("SSLHandshake", testParams, ortn);
+                       goto cleanup;
+       }
+
+
+       /*
+        * Unlike other ping tests we don't bother with a GET - just validate
+        * the handshake
+        */
+       ortn = SSLGetNegotiatedCipher(ctx, &negCipher);
+       if(ortn) {
+               dumpErrInfo("SSLHandshake", testParams, ortn);
+               goto cleanup;
+       }
+
+       /* here is really what we're testing */
+       if(negCipher != testParams->cipherSuite) {
+               printf("***Cipher mismatch for ");
+               dumpParams(testParams);
+               printf("Negotiated cipher: %s\n", sslGetCipherSuiteString(negCipher));
+               ortn = errSecIO;
+               goto cleanup;
+       }
+       if(testParams->expCurve != SSL_Curve_None) {
+               SSL_ECDSA_NamedCurve actNegCurve;
+               ortn = SSLGetNegotiatedCurve(ctx, &actNegCurve);
+               if(ortn) {
+                       printSslErrStr("SSLGetNegotiatedCurve", ortn);
+                       goto cleanup;
+               }
+               if(actNegCurve != testParams->expCurve) {
+                       printf("***Negotiated curve error\n");
+                       printf("Specified curve: %s\n", sslCurveString(testParams->specCurve));
+                       printf("Expected  curve: %s\n", sslCurveString(testParams->expCurve));
+                       printf("Obtained  curve: %s\n", sslCurveString(actNegCurve));
+                       ortn = errSecIO;
+                       goto cleanup;
+               }
+       }
+       if(testParams->keychain) {
+               /* Verify client auth */
+               SSLClientCertificateState authState;
+               ortn = SSLGetClientCertificateState(ctx, &authState);
+               if(ortn) {
+                       printSslErrStr("SSLGetClientCertificateState", ortn);
+                       goto cleanup;
+               }
+               if(authState != kSSLClientCertSent) {
+                       printf("***Unexpected ClientCertificateState\n");
+                       printf("   Expected: ClientCertSent\n");
+                       printf("   Received: %s\n", sslGetClientCertStateString(authState));
+                       ortn = errSecIO;
+                       goto cleanup;
+               }
+       }
+
+    ortn = SSLClose(ctx);
+
+cleanup:
+       if(sock) {
+               endpointShutdown(sock);
+       }
+       if(ctx) {
+           SSLDisposeContext(ctx);
+       }
+       return (int)ortn;
+}
+
+
+int main(int argc, char **argv)
+{
+       int             ourRtn = 0;
+       bool            quiet = false;
+       int                     nonBlocking = false;
+       unsigned        minDex = 0;
+       unsigned        maxDex = NUM_TEST_PARAMS-1;
+       bool            doPause = false;
+
+       extern char *optarg;
+       int arg;
+       while ((arg = getopt(argc, argv, "t:bpqh")) != -1) {
+               switch (arg) {
+                       case 't':
+                               minDex = maxDex = atoi(optarg);
+                               if(minDex > (NUM_TEST_PARAMS - 1)) {
+                                       printf("***max test number is %u.\n", (unsigned)NUM_TEST_PARAMS);
+                                       exit(1);
+                               }
+                               break;
+                       case 'q':
+                               quiet = true;
+                               break;
+                       case 'b':
+                               nonBlocking = true;
+                               break;
+                       case 'p':
+                               doPause = true;
+                               break;
+                       default:
+                               usage(argv);
+               }
+       }
+       if(optind != argc) {
+               usage(argv);
+       }
+
+#if NO_SERVER
+# if DEBUG
+    securityd_init(NULL);
+# endif
+#endif
+
+       #if IGNORE_SIGPIPE
+       signal(SIGPIPE, sigpipe);
+       #endif
+
+       //testStartBanner("sslEcdsa", argc, argv);
+
+       if(doPause) {
+               fpurge(stdin);
+               printf("Pausing at top of loop; CR to continue: ");
+               fflush(stdout);
+               getchar();
+       }
+
+       for(unsigned dex=minDex; dex<=maxDex; dex++) {
+               const EcdsaTestParams *testParams = &ecdsaTestParams[dex];
+               if(!quiet) {
+                       printf("[%u]: ", dex);
+                       dumpParams(testParams);
+               }
+               ourRtn = doSslPing(testParams, quiet, nonBlocking);
+               if(ourRtn) {
+            //printf("** Test %u failed **\n", dex);
+                       //if(testError(quiet)) {
+                       //  break;
+                       //}
+               }
+       }
+
+       if(doPause) {
+               fpurge(stdin);
+               printf("Pausing at end of loop; CR to continue: ");
+               fflush(stdout);
+               getchar();
+       }
+
+       if(!quiet) {
+               if(ourRtn == 0) {
+                       printf("===== sslEcdsa test PASSED =====\n");
+               }
+               else {
+                       printf("****sslEcdsa test FAILED\n");
+               }
+       }
+
+       return ourRtn;
+}