+ EVP_MD_CTX_free(mdata->ctx);
+ sk_EVP_TEST_BUFFER_pop_free(mdata->input, evp_test_buffer_free);
+ OPENSSL_free(mdata->osin);
+ OPENSSL_free(mdata->output);
+ OPENSSL_free(mdata);
+ t->data = NULL;
+}
+
+static int digestsigver_test_parse(EVP_TEST *t,
+ const char *keyword, const char *value)
+{
+ DIGESTSIGN_DATA *mdata = t->data;
+
+ if (strcmp(keyword, "Key") == 0) {
+ EVP_PKEY *pkey = NULL;
+ int rv = 0;
+
+ if (mdata->is_verify)
+ rv = find_key(&pkey, value, public_keys);
+ if (rv == 0)
+ rv = find_key(&pkey, value, private_keys);
+ if (rv == 0 || pkey == NULL) {
+ t->skip = 1;
+ return 1;
+ }
+ if (mdata->is_verify) {
+ if (!EVP_DigestVerifyInit(mdata->ctx, &mdata->pctx, mdata->md,
+ NULL, pkey))
+ t->err = "DIGESTVERIFYINIT_ERROR";
+ return 1;
+ }
+ if (!EVP_DigestSignInit(mdata->ctx, &mdata->pctx, mdata->md, NULL,
+ pkey))
+ t->err = "DIGESTSIGNINIT_ERROR";
+ return 1;
+ }
+
+ if (strcmp(keyword, "Input") == 0) {
+ if (mdata->is_oneshot)
+ return parse_bin(value, &mdata->osin, &mdata->osin_len);
+ return evp_test_buffer_append(value, &mdata->input);
+ }
+ if (strcmp(keyword, "Output") == 0)
+ return parse_bin(value, &mdata->output, &mdata->output_len);
+
+ if (!mdata->is_oneshot) {
+ if (strcmp(keyword, "Count") == 0)
+ return evp_test_buffer_set_count(value, mdata->input);
+ if (strcmp(keyword, "Ncopy") == 0)
+ return evp_test_buffer_ncopy(value, mdata->input);
+ }
+ if (strcmp(keyword, "Ctrl") == 0) {
+ if (mdata->pctx == NULL)
+ return -1;
+ return pkey_test_ctrl(t, mdata->pctx, value);
+ }
+ return 0;
+}
+
+static int digestsign_update_fn(void *ctx, const unsigned char *buf,
+ size_t buflen)
+{
+ return EVP_DigestSignUpdate(ctx, buf, buflen);
+}
+
+static int digestsign_test_run(EVP_TEST *t)
+{
+ DIGESTSIGN_DATA *expected = t->data;
+ unsigned char *got = NULL;
+ size_t got_len;
+
+ if (!evp_test_buffer_do(expected->input, digestsign_update_fn,
+ expected->ctx)) {
+ t->err = "DIGESTUPDATE_ERROR";
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(expected->ctx, NULL, &got_len)) {
+ t->err = "DIGESTSIGNFINAL_LENGTH_ERROR";
+ goto err;
+ }
+ if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+ t->err = "MALLOC_FAILURE";
+ goto err;
+ }
+ if (!EVP_DigestSignFinal(expected->ctx, got, &got_len)) {
+ t->err = "DIGESTSIGNFINAL_ERROR";
+ goto err;
+ }
+ if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
+ expected->output, expected->output_len,
+ got, got_len))
+ goto err;
+
+ t->err = NULL;
+ err:
+ OPENSSL_free(got);
+ return 1;
+}
+
+static const EVP_TEST_METHOD digestsign_test_method = {
+ "DigestSign",
+ digestsign_test_init,
+ digestsigver_test_cleanup,
+ digestsigver_test_parse,
+ digestsign_test_run
+};
+
+static int digestverify_test_init(EVP_TEST *t, const char *alg)
+{
+ return digestsigver_test_init(t, alg, 1, 0);
+}
+
+static int digestverify_update_fn(void *ctx, const unsigned char *buf,
+ size_t buflen)
+{
+ return EVP_DigestVerifyUpdate(ctx, buf, buflen);
+}
+
+static int digestverify_test_run(EVP_TEST *t)
+{
+ DIGESTSIGN_DATA *mdata = t->data;
+
+ if (!evp_test_buffer_do(mdata->input, digestverify_update_fn, mdata->ctx)) {
+ t->err = "DIGESTUPDATE_ERROR";
+ return 1;
+ }
+
+ if (EVP_DigestVerifyFinal(mdata->ctx, mdata->output,
+ mdata->output_len) <= 0)
+ t->err = "VERIFY_ERROR";
+ return 1;
+}
+
+static const EVP_TEST_METHOD digestverify_test_method = {
+ "DigestVerify",
+ digestverify_test_init,
+ digestsigver_test_cleanup,
+ digestsigver_test_parse,
+ digestverify_test_run
+};
+
+static int oneshot_digestsign_test_init(EVP_TEST *t, const char *alg)
+{
+ return digestsigver_test_init(t, alg, 0, 1);
+}
+
+static int oneshot_digestsign_test_run(EVP_TEST *t)
+{
+ DIGESTSIGN_DATA *expected = t->data;
+ unsigned char *got = NULL;
+ size_t got_len;
+
+ if (!EVP_DigestSign(expected->ctx, NULL, &got_len,
+ expected->osin, expected->osin_len)) {
+ t->err = "DIGESTSIGN_LENGTH_ERROR";
+ goto err;
+ }
+ if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+ t->err = "MALLOC_FAILURE";
+ goto err;
+ }
+ if (!EVP_DigestSign(expected->ctx, got, &got_len,
+ expected->osin, expected->osin_len)) {
+ t->err = "DIGESTSIGN_ERROR";
+ goto err;
+ }
+ if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
+ expected->output, expected->output_len,
+ got, got_len))
+ goto err;
+
+ t->err = NULL;
+ err:
+ OPENSSL_free(got);
+ return 1;
+}
+
+static const EVP_TEST_METHOD oneshot_digestsign_test_method = {
+ "OneShotDigestSign",
+ oneshot_digestsign_test_init,
+ digestsigver_test_cleanup,
+ digestsigver_test_parse,
+ oneshot_digestsign_test_run
+};
+
+static int oneshot_digestverify_test_init(EVP_TEST *t, const char *alg)
+{
+ return digestsigver_test_init(t, alg, 1, 1);
+}
+
+static int oneshot_digestverify_test_run(EVP_TEST *t)
+{
+ DIGESTSIGN_DATA *mdata = t->data;
+
+ if (EVP_DigestVerify(mdata->ctx, mdata->output, mdata->output_len,
+ mdata->osin, mdata->osin_len) <= 0)
+ t->err = "VERIFY_ERROR";
+ return 1;
+}
+
+static const EVP_TEST_METHOD oneshot_digestverify_test_method = {
+ "OneShotDigestVerify",
+ oneshot_digestverify_test_init,
+ digestsigver_test_cleanup,
+ digestsigver_test_parse,
+ oneshot_digestverify_test_run
+};
+
+
+/**
+*** PARSING AND DISPATCH
+**/
+
+static const EVP_TEST_METHOD *evp_test_list[] = {
+ &cipher_test_method,
+ &digest_test_method,
+ &digestsign_test_method,
+ &digestverify_test_method,
+ &encode_test_method,
+ &kdf_test_method,
+ &pkey_kdf_test_method,
+ &keypair_test_method,
+ &keygen_test_method,
+ &mac_test_method,
+ &oneshot_digestsign_test_method,
+ &oneshot_digestverify_test_method,
+ &pbe_test_method,
+ &pdecrypt_test_method,
+ &pderive_test_method,
+ &psign_test_method,
+ &pverify_recover_test_method,
+ &pverify_test_method,
+ NULL
+};
+
+static const EVP_TEST_METHOD *find_test(const char *name)
+{
+ const EVP_TEST_METHOD **tt;
+
+ for (tt = evp_test_list; *tt; tt++) {
+ if (strcmp(name, (*tt)->name) == 0)
+ return *tt;
+ }
+ return NULL;
+}
+
+static void clear_test(EVP_TEST *t)