+
+ for (count = 0; COND(nb_iter); count++) {
+ if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL))
+ return -1;
+ }
+ return count;
+}
+
+#ifndef OPENSSL_NO_RSA
+static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */
+
+static int RSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ unsigned int *rsa_num = &tempargs->siglen;
+ RSA **rsa_key = tempargs->rsa_key;
+ int ret, count;
+ for (count = 0; COND(rsa_c[testnum][0]); count++) {
+ ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "RSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int RSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ unsigned int rsa_num = tempargs->siglen;
+ RSA **rsa_key = tempargs->rsa_key;
+ int ret, count;
+ for (count = 0; COND(rsa_c[testnum][1]); count++) {
+ ret = RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
+ if (ret <= 0) {
+ BIO_printf(bio_err, "RSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+static long dsa_c[DSA_NUM][2];
+static int DSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ DSA **dsa_key = tempargs->dsa_key;
+ unsigned int *siglen = &tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(dsa_c[testnum][0]); count++) {
+ ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "DSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int DSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ unsigned char *buf2 = tempargs->buf2;
+ DSA **dsa_key = tempargs->dsa_key;
+ unsigned int siglen = tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(dsa_c[testnum][1]); count++) {
+ ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
+ if (ret <= 0) {
+ BIO_printf(bio_err, "DSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+static long ecdsa_c[EC_NUM][2];
+static int ECDSA_sign_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ EC_KEY **ecdsa = tempargs->ecdsa;
+ unsigned char *ecdsasig = tempargs->buf2;
+ unsigned int *ecdsasiglen = &tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
+ ret = ECDSA_sign(0, buf, 20,
+ ecdsasig, ecdsasiglen, ecdsa[testnum]);
+ if (ret == 0) {
+ BIO_printf(bio_err, "ECDSA sign failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+static int ECDSA_verify_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ unsigned char *buf = tempargs->buf;
+ EC_KEY **ecdsa = tempargs->ecdsa;
+ unsigned char *ecdsasig = tempargs->buf2;
+ unsigned int ecdsasiglen = tempargs->siglen;
+ int ret, count;
+ for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
+ ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen,
+ ecdsa[testnum]);
+ if (ret != 1) {
+ BIO_printf(bio_err, "ECDSA verify failure\n");
+ ERR_print_errors(bio_err);
+ count = -1;
+ break;
+ }
+ }
+ return count;
+}
+
+/* ******************************************************************** */
+static long ecdh_c[EC_NUM][1];
+
+static int ECDH_compute_key_loop(void *args)
+{
+ loopargs_t *tempargs = *(loopargs_t **)args;
+ EC_KEY **ecdh_a = tempargs->ecdh_a;
+ EC_KEY **ecdh_b = tempargs->ecdh_b;
+ unsigned char *secret_a = tempargs->secret_a;
+ int count;
+ size_t outlen = tempargs->outlen;
+ kdf_fn kdf = tempargs->kdf;
+
+ for (count = 0; COND(ecdh_c[testnum][0]); count++) {
+ ECDH_compute_key(secret_a, outlen,
+ EC_KEY_get0_public_key(ecdh_b[testnum]),
+ ecdh_a[testnum], kdf);
+ }
+ return count;
+}
+
+static const size_t KDF1_SHA1_len = 20;
+static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
+ size_t *outlen)
+{
+ if (*outlen < SHA_DIGEST_LENGTH)
+ return NULL;
+ *outlen = SHA_DIGEST_LENGTH;
+ return SHA1(in, inlen, out);
+}
+#endif /* OPENSSL_NO_EC */
+
+static int run_benchmark(int async_jobs,
+ int (*loop_function)(void *), loopargs_t *loopargs)
+{
+ int job_op_count = 0;
+ int total_op_count = 0;
+ int num_inprogress = 0;
+ int error = 0, i = 0, ret = 0;
+ OSSL_ASYNC_FD job_fd = 0;
+ size_t num_job_fds = 0;
+
+ run = 1;
+
+ if (async_jobs == 0) {
+ return loop_function((void *)&loopargs);
+ }
+
+ for (i = 0; i < async_jobs && !error; i++) {
+ loopargs_t *looparg_item = loopargs + i;
+
+ /* Copy pointer content (looparg_t item address) into async context */
+ ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx,
+ &job_op_count, loop_function,
+ (void *)&looparg_item, sizeof(looparg_item));
+ switch (ret) {
+ case ASYNC_PAUSE:
+ ++num_inprogress;
+ break;
+ case ASYNC_FINISH:
+ if (job_op_count == -1) {
+ error = 1;
+ } else {
+ total_op_count += job_op_count;
+ }
+ break;
+ case ASYNC_NO_JOBS:
+ case ASYNC_ERR:
+ BIO_printf(bio_err, "Failure in the job\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ }
+
+ while (num_inprogress > 0) {
+#if defined(OPENSSL_SYS_WINDOWS)
+ DWORD avail = 0;
+#elif defined(OPENSSL_SYS_UNIX)
+ int select_result = 0;
+ OSSL_ASYNC_FD max_fd = 0;
+ fd_set waitfdset;
+
+ FD_ZERO(&waitfdset);
+
+ for (i = 0; i < async_jobs && num_inprogress > 0; i++) {
+ if (loopargs[i].inprogress_job == NULL)
+ continue;
+
+ if (!ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, NULL, &num_job_fds)
+ || num_job_fds > 1) {
+ BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, &num_job_fds);
+ FD_SET(job_fd, &waitfdset);
+ if (job_fd > max_fd)
+ max_fd = job_fd;
+ }
+
+ if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) {
+ BIO_printf(bio_err,
+ "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). "
+ "Decrease the value of async_jobs\n",
+ max_fd, FD_SETSIZE);
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+
+ select_result = select(max_fd + 1, &waitfdset, NULL, NULL, NULL);
+ if (select_result == -1 && errno == EINTR)
+ continue;
+
+ if (select_result == -1) {
+ BIO_printf(bio_err, "Failure in the select\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+
+ if (select_result == 0)
+ continue;
+#endif
+
+ for (i = 0; i < async_jobs; i++) {
+ if (loopargs[i].inprogress_job == NULL)
+ continue;
+
+ if (!ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, NULL, &num_job_fds)
+ || num_job_fds > 1) {
+ BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd, &num_job_fds);
+
+#if defined(OPENSSL_SYS_UNIX)
+ if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset))
+ continue;
+#elif defined(OPENSSL_SYS_WINDOWS)
+ if (num_job_fds == 1
+ && !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL)
+ && avail > 0)
+ continue;
+#endif
+
+ ret = ASYNC_start_job(&loopargs[i].inprogress_job,
+ loopargs[i].wait_ctx, &job_op_count, loop_function,
+ (void *)(loopargs + i), sizeof(loopargs_t));
+ switch (ret) {
+ case ASYNC_PAUSE:
+ break;
+ case ASYNC_FINISH:
+ if (job_op_count == -1) {
+ error = 1;
+ } else {
+ total_op_count += job_op_count;
+ }
+ --num_inprogress;
+ loopargs[i].inprogress_job = NULL;
+ break;
+ case ASYNC_NO_JOBS:
+ case ASYNC_ERR:
+ --num_inprogress;
+ loopargs[i].inprogress_job = NULL;
+ BIO_printf(bio_err, "Failure in the job\n");
+ ERR_print_errors(bio_err);
+ error = 1;
+ break;
+ }
+ }
+ }
+
+ return error ? -1 : total_op_count;
+}
+
+int speed_main(int argc, char **argv)
+{
+ ENGINE *e = NULL;
+ loopargs_t *loopargs = NULL;
+ int async_init = 0;
+ int loopargs_len = 0;
+ char *prog;
+#ifndef OPENSSL_NO_ENGINE
+ const char *engine_id = NULL;
+#endif
+ const EVP_CIPHER *evp_cipher = NULL;
+ double d = 0.0;
+ OPTION_CHOICE o;
+ int multiblock = 0, pr_header = 0;
+ int doit[ALGOR_NUM] = { 0 };
+ int ret = 1, i, k, misalign = 0;
+ long count = 0;
+#ifndef NO_FORK
+ int multi = 0;
+#endif
+ int async_jobs = 0;
+#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
+ || !defined(OPENSSL_NO_EC)
+ long rsa_count = 1;
+#endif
+
+ /* What follows are the buffers and key material. */