+
+#define TBUF_MAXSIZE 2048
+
+static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx,
+ const EVP_MD *md, EVP_PKEY *pkey, BIO *in,
+ unsigned char *sig, int siglen,
+ unsigned char **out, size_t *poutlen)
+{
+ int rv = 0;
+ EVP_MD_CTX *mctx = NULL;
+ unsigned char tbuf[TBUF_MAXSIZE];
+ int tbuf_len = 0;
+
+ if ((mctx = EVP_MD_CTX_new()) == NULL) {
+ BIO_printf(bio_err, "Error: out of memory\n");
+ return rv;
+ }
+ EVP_MD_CTX_set_pkey_ctx(mctx, ctx);
+
+ switch(pkey_op) {
+ case EVP_PKEY_OP_VERIFY:
+ if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1)
+ goto end;
+ for (;;) {
+ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (tbuf_len == 0)
+ break;
+ if (tbuf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)tbuf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error verifying raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen);
+ break;
+ case EVP_PKEY_OP_SIGN:
+ if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1)
+ goto end;
+ for (;;) {
+ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE);
+ if (tbuf_len == 0)
+ break;
+ if (tbuf_len < 0) {
+ BIO_printf(bio_err, "Error reading raw input data\n");
+ goto end;
+ }
+ rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)tbuf_len);
+ if (rv != 1) {
+ BIO_printf(bio_err, "Error signing raw input data\n");
+ goto end;
+ }
+ }
+ rv = EVP_DigestSignFinal(mctx, NULL, poutlen);
+ if (rv == 1 && out != NULL) {
+ *out = app_malloc(*poutlen, "buffer output");
+ rv = EVP_DigestSignFinal(mctx, *out, poutlen);
+ }
+ break;
+ }
+
+ end:
+ EVP_MD_CTX_free(mctx);
+ return rv;
+}