Esempio n. 1
0
static int test_EVP_DigestSignInit(void)
{
    int ret = 0;
    EVP_PKEY *pkey = NULL;
    unsigned char *sig = NULL;
    size_t sig_len = 0;
    EVP_MD_CTX md_ctx, md_ctx_verify;

    EVP_MD_CTX_init(&md_ctx);
    EVP_MD_CTX_init(&md_ctx_verify);

    pkey = load_example_rsa_key();
    if (pkey == NULL ||
        !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
        !EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg))) {
        goto out;
    }
    /* Determine the size of the signature. */
    if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
        goto out;
    }
    /* Sanity check for testing. */
    if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
        fprintf(stderr, "sig_len mismatch\n");
        goto out;
    }

    sig = OPENSSL_malloc(sig_len);
    if (sig == NULL || !EVP_DigestSignFinal(&md_ctx, sig, &sig_len)) {
        goto out;
    }

    /* Ensure that the signature round-trips. */
    if (!EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey)
        || !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg))
        || !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
        goto out;
    }

    ret = 1;

 out:
    if (!ret) {
        ERR_print_errors_fp(stderr);
    }

    EVP_MD_CTX_cleanup(&md_ctx);
    EVP_MD_CTX_cleanup(&md_ctx_verify);
    EVP_PKEY_free(pkey);
    if (sig) {
        OPENSSL_free(sig);
    }

    return ret;
}
Esempio n. 2
0
/* test_algorithm_roundtrip signs a message using an already-initialized
 * |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
 * AlgorithmIdentifier to verify the signature. */
static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
  int ret = 0;
  uint8_t *sig = NULL;
  size_t sig_len = 0;
  EVP_MD_CTX md_ctx_verify;
  X509_ALGOR *algor = NULL;

  EVP_MD_CTX_init(&md_ctx_verify);

  if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
    goto out;
  }

  /* Save the algorithm. */
  algor = X509_ALGOR_new();
  if (algor == NULL || !EVP_DigestSignAlgorithm(md_ctx, algor)) {
    goto out;
  }

  /* Determine the size of the signature. */
  if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
    goto out;
  }
  /* Sanity check for testing. */
  if (sig_len != EVP_PKEY_size(pkey)) {
    fprintf(stderr, "sig_len mismatch\n");
    goto out;
  }

  sig = malloc(sig_len);
  if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
    goto out;
  }

  /* Ensure that the signature round-trips. */
  if (!EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) ||
      !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
      !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
    goto out;
  }

  ret = 1;

out:
  EVP_MD_CTX_cleanup(&md_ctx_verify);
  if (sig) {
    free(sig);
  }
  if (algor) {
    X509_ALGOR_free(algor);
  }

  return ret;
}
Esempio n. 3
0
static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
                              size_t max_out, const EVP_MD *md,
                              const uint8_t *in, size_t in_len) {
  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
            EVP_DigestSignUpdate(&ctx, in, in_len) &&
            EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
Esempio n. 4
0
/*
 * Generates the mac for the Finished message. Returns the length of the MAC or
 * 0 on error.
 */
size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
                             unsigned char *out)
{
    const EVP_MD *md = ssl_handshake_md(s);
    unsigned char hash[EVP_MAX_MD_SIZE];
    size_t hashlen, ret = 0;
    EVP_PKEY *key = NULL;
    EVP_MD_CTX *ctx = EVP_MD_CTX_new();

    if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) {
        /* SSLfatal() already called */
        goto err;
    }

    if (str == s->method->ssl3_enc->server_finished_label) {
        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
                                           s->server_finished_secret, hashlen);
    } else if (SSL_IS_FIRST_HANDSHAKE(s)) {
        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
                                           s->client_finished_secret, hashlen);
    } else {
        unsigned char finsecret[EVP_MAX_MD_SIZE];

        if (!tls13_derive_finishedkey(s, ssl_handshake_md(s),
                                      s->client_app_traffic_secret,
                                      finsecret, hashlen))
            goto err;

        key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret,
                                           hashlen);
        OPENSSL_cleanse(finsecret, sizeof(finsecret));
    }

    if (key == NULL
            || ctx == NULL
            || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0
            || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0
            || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) {
        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC,
                 ERR_R_INTERNAL_ERROR);
        goto err;
    }

    ret = hashlen;
 err:
    EVP_PKEY_free(key);
    EVP_MD_CTX_free(ctx);
    return ret;
}
Esempio n. 5
0
static int sign_it(const unsigned char *msg, size_t mlen, unsigned char **sig, size_t *slen, EVP_PKEY *pkey) {
    int result = GS_FAILED;
    
    *sig = NULL;
    *slen = 0;
    
    EVP_MD_CTX *ctx = EVP_MD_CTX_create();
    if (ctx == NULL)
        return GS_FAILED;
    
    const EVP_MD *md = EVP_get_digestbyname("SHA256");
    if (md == NULL)
        goto cleanup;
    
    int rc = EVP_DigestInit_ex(ctx, md, NULL);
    if (rc != 1)
        goto cleanup;
    
    rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
    if (rc != 1)
        goto cleanup;
    
    rc = EVP_DigestSignUpdate(ctx, msg, mlen);
    if (rc != 1)
        goto cleanup;
    
    size_t req = 0;
    rc = EVP_DigestSignFinal(ctx, NULL, &req);
    if (rc != 1 || !(req > 0))
        goto cleanup;
    
    *sig = OPENSSL_malloc(req);
    if (*sig == NULL)
        goto cleanup;
    
    *slen = req;
    rc = EVP_DigestSignFinal(ctx, *sig, slen);
    if (rc != 1 || req != *slen)
        goto cleanup;
    
    result = GS_OK;
    
cleanup:
    EVP_MD_CTX_destroy(ctx);
    ctx = NULL;
    
    return result;
}
Esempio n. 6
0
static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
                              size_t max_out, const EVP_MD *md,
                              const uint8_t *in, size_t in_len) {
  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  EVP_PKEY_CTX *pctx;
  int ret =
      EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
      EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
      EVP_DigestSignUpdate(&ctx, in, in_len) &&
      EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
Esempio n. 7
0
static int test_EVP_DigestSignInit(void)
{
    int ret = 0;
    EVP_PKEY *pkey = NULL;
    unsigned char *sig = NULL;
    size_t sig_len = 0;
    EVP_MD_CTX *md_ctx, *md_ctx_verify = NULL;

    if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())
            || !TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())
            || !TEST_ptr(pkey = load_example_rsa_key()))
        goto out;

    if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey))
            || !TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))))
        goto out;

    /* Determine the size of the signature. */
    if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))
            || !TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey)))
        goto out;

    if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))
            || !TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len)))
        goto out;

    /* Ensure that the signature round-trips. */
    if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sha256(),
                                        NULL, pkey))
            || !TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify,
                                                 kMsg, sizeof(kMsg)))
            || !TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len)))
        goto out;

    ret = 1;

 out:
    EVP_MD_CTX_free(md_ctx);
    EVP_MD_CTX_free(md_ctx_verify);
    EVP_PKEY_free(pkey);
    OPENSSL_free(sig);

    return ret;
}
Esempio n. 8
0
char *compute_and_encode_signature(const grpc_auth_json_key *json_key,
                                   const char *signature_algorithm,
                                   const char *to_sign) {
  const EVP_MD *md = openssl_digest_from_algorithm(signature_algorithm);
  EVP_MD_CTX *md_ctx = NULL;
  EVP_PKEY *key = EVP_PKEY_new();
  size_t sig_len = 0;
  unsigned char *sig = NULL;
  char *result = NULL;
  if (md == NULL) return NULL;
  md_ctx = EVP_MD_CTX_create();
  if (md_ctx == NULL) {
    gpr_log(GPR_ERROR, "Could not create MD_CTX");
    goto end;
  }
  EVP_PKEY_set1_RSA(key, json_key->private_key);
  if (EVP_DigestSignInit(md_ctx, NULL, md, NULL, key) != 1) {
    gpr_log(GPR_ERROR, "DigestInit failed.");
    goto end;
  }
  if (EVP_DigestSignUpdate(md_ctx, to_sign, strlen(to_sign)) != 1) {
    gpr_log(GPR_ERROR, "DigestUpdate failed.");
    goto end;
  }
  if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
    gpr_log(GPR_ERROR, "DigestFinal (get signature length) failed.");
    goto end;
  }
  sig = gpr_malloc(sig_len);
  if (EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
    gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
    goto end;
  }
  result = grpc_base64_encode(sig, sig_len, 1, 0);

end:
  if (key != NULL) EVP_PKEY_free(key);
  if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
  if (sig != NULL) gpr_free(sig);
  return result;
}
Esempio n. 9
0
QByteArray
NvPairingManager::signMessage(QByteArray message)
{
    EVP_MD_CTX *ctx = EVP_MD_CTX_create();
    THROW_BAD_ALLOC_IF_NULL(ctx);

    const EVP_MD *md = EVP_get_digestbyname("SHA256");
    THROW_BAD_ALLOC_IF_NULL(md);

    EVP_DigestInit_ex(ctx, md, NULL);
    EVP_DigestSignInit(ctx, NULL, md, NULL, m_PrivateKey);
    EVP_DigestSignUpdate(ctx, reinterpret_cast<unsigned char*>(message.data()), message.length());

    size_t signatureLength = 0;
    EVP_DigestSignFinal(ctx, NULL, &signatureLength);

    QByteArray signature((int)signatureLength, 0);
    EVP_DigestSignFinal(ctx, reinterpret_cast<unsigned char*>(signature.data()), &signatureLength);

    EVP_MD_CTX_destroy(ctx);

    return signature;
}
Esempio n. 10
0
int tls1_mac(SSL *ssl, unsigned char *md, int send)
	{
	SSL3_RECORD *rec;
	unsigned char *seq;
	EVP_MD_CTX *hash;
	size_t md_size;
	int i;
	EVP_MD_CTX hmac, *mac_ctx;
	unsigned char buf[5]; 
	int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
	int t;

	if (send)
		{
		rec= &(ssl->s3->wrec);
		seq= &(ssl->s3->write_sequence[0]);
		hash=ssl->write_hash;
		}
	else
		{
		rec= &(ssl->s3->rrec);
		seq= &(ssl->s3->read_sequence[0]);
		hash=ssl->read_hash;
		}

	t=EVP_MD_CTX_size(hash);
	TINYCLR_SSL_ASSERT(t >= 0);
	md_size=t;

	buf[0]=rec->type;
	buf[1]=(unsigned char)(ssl->version>>8);
	buf[2]=(unsigned char)(ssl->version);
	buf[3]=rec->length>>8;
	buf[4]=rec->length&0xff;

	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
	if (stream_mac) 
		{
			mac_ctx = hash;
		}
		else
		{
			EVP_MD_CTX_copy(&hmac,hash);
			mac_ctx = &hmac;
		}

	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
		{
		unsigned char dtlsseq[8],*p=dtlsseq;

		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
		TINYCLR_SSL_MEMCPY (p,&seq[2],6);

		EVP_DigestSignUpdate(mac_ctx,dtlsseq,8);
		}
	else
		EVP_DigestSignUpdate(mac_ctx,seq,8);

	EVP_DigestSignUpdate(mac_ctx,buf,5);
	EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
	t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
	TINYCLR_SSL_ASSERT(t > 0);
		
	if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
#ifdef TLS_DEBUG
TINYCLR_SSL_PRINTF("sec=");
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",mac_sec[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("seq=");
{int z; for (z=0; z<8; z++) TINYCLR_SSL_PRINTF("%02X ",seq[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("buf=");
{int z; for (z=0; z<5; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif

	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
		{
		for (i=7; i>=0; i--)
			{
			++seq[i];
			if (seq[i] != 0) break; 
			}
		}

#ifdef TLS_DEBUG
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",md[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif
	return(md_size);
	}
Esempio n. 11
0
File: poly1305.c Progetto: bmk/otp
/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */
ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, Text) */
#ifdef HAVE_POLY1305
    ErlNifBinary key_bin, text, ret_bin;
    ERL_NIF_TERM ret;
    EVP_PKEY *key = NULL;
    EVP_MD_CTX *mctx = NULL;
    EVP_PKEY_CTX *pctx = NULL;
    const EVP_MD *md = NULL;
    size_t size;
    int ret_bin_alloc = 0;

    ASSERT(argc == 2);

    if (!enif_inspect_binary(env, argv[0], &key_bin))
        goto bad_arg;
    if (key_bin.size != 32)
        goto bad_arg;
    if (!enif_inspect_binary(env, argv[1], &text))
        goto bad_arg;

    if ((key = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data,  key_bin.size)) == NULL)
        goto err;

    if ((mctx = EVP_MD_CTX_new()) == NULL)
        goto err;
    if (EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) != 1)
        goto err;
    if (EVP_DigestSignUpdate(mctx, text.data, text.size) != 1)
        goto err;

    if (EVP_DigestSignFinal(mctx, NULL, &size) != 1)
        goto err;
    if (!enif_alloc_binary(size, &ret_bin))
        goto err;
    ret_bin_alloc = 1;
    if (EVP_DigestSignFinal(mctx, ret_bin.data, &size) != 1)
        goto err;

    if (size != ret_bin.size) {
        if (!enif_realloc_binary(&ret_bin, size))
            goto err;
    }

    ret = enif_make_binary(env, &ret_bin);
    ret_bin_alloc = 0;
    goto done;

 bad_arg:
    return enif_make_badarg(env);

 err:
    if (ret_bin_alloc)
        enif_release_binary(&ret_bin);
    ret = atom_error;

 done:
    if (mctx)
        EVP_MD_CTX_free(mctx);
    if (key)
        EVP_PKEY_free(key);
    return ret;

#else
    return enif_raise_exception(env, atom_notsup);
#endif
}
Esempio n. 12
0
sgx_status_t sgx_rsa3072_sign(const uint8_t * p_data,
	uint32_t data_size,
	const sgx_rsa3072_key_t * p_key,
	sgx_rsa3072_signature_t * p_signature)
{
	if ((p_data == NULL) || (data_size < 1) || (p_key == NULL) ||
		(p_signature == NULL))
	{
		return SGX_ERROR_INVALID_PARAMETER;
	}

	sgx_status_t retval = SGX_ERROR_UNEXPECTED;
	RSA *priv_rsa_key = NULL;
	EVP_PKEY* priv_pkey = NULL;
	BIGNUM *n = NULL;
	BIGNUM *d = NULL;
	BIGNUM *e = NULL;
	EVP_MD_CTX* ctx = NULL;
	const EVP_MD* sha256_md = NULL;
	size_t siglen = SGX_RSA3072_KEY_SIZE;
	int ret = 0;

	CLEAR_OPENSSL_ERROR_QUEUE;

	do {
		// converts the modulus value of rsa key, represented as positive integer in little-endian into a BIGNUM
		//
		n = BN_lebin2bn((const unsigned char *)p_key->mod, sizeof(p_key->mod), 0);
		if (n == NULL) {
			break;
		}

		// converts the private exp value of rsa key, represented as positive integer in little-endian into a BIGNUM
		//
		d = BN_lebin2bn((const unsigned char *)p_key->d, sizeof(p_key->d), 0);
		if (d == NULL) {
			break;
		}

		// converts the public exp value of rsa key, represented as positive integer in little-endian into a BIGNUM
		//
		e = BN_lebin2bn((const unsigned char *)p_key->e, sizeof(p_key->e), 0);
		if (e == NULL) {
			break;
		}

		// allocates and initializes an RSA key structure
		//
		priv_rsa_key = RSA_new();
		if (priv_rsa_key == NULL) {
			retval = SGX_ERROR_OUT_OF_MEMORY;
			break;
		}

		// sets the modulus, private exp and public exp values of the RSA key
		//
		if (RSA_set0_key(priv_rsa_key, n, e, d) != 1) {
			BN_clear_free(n);
			BN_clear_free(d);
			BN_clear_free(e);
			break;
		}

		// allocates an empty EVP_PKEY structure
		//
		priv_pkey = EVP_PKEY_new();
		if (priv_pkey == NULL) {
			retval = SGX_ERROR_OUT_OF_MEMORY;
			break;
		}

		// set the referenced key to pub_rsa_key, however these use the supplied key internally and so key will be freed when the parent pkey is freed
		//
		if (EVP_PKEY_assign_RSA(priv_pkey, priv_rsa_key) != 1) {
			RSA_free(priv_rsa_key);
			break;
		}

		// allocates, initializes and returns a digest context
		//
		ctx = EVP_MD_CTX_new();
		if (NULL == ctx) {
			retval = SGX_ERROR_OUT_OF_MEMORY;
			break;
		}

		// return EVP_MD structures for SHA256 digest algorithm */
		//
		sha256_md = EVP_sha256();
		if (sha256_md == NULL) {
			break;
		}

		// sets up signing context ctx to use digest type
		//
		if (EVP_DigestSignInit(ctx, NULL, sha256_md, NULL, priv_pkey) <= 0) {
			break;
		}

		// hashes data_size bytes of data at p_data into the signature context ctx
		//
		if (EVP_DigestSignUpdate(ctx, (const void *)p_data, data_size) <= 0) {
			break;
		}

		// signs the data in ctx places the signature in p_signature.
		//
		ret = EVP_DigestSignFinal(ctx, (unsigned char *)p_signature, &siglen);//fails
		if (ret <= 0) {
			break;
		}

		// validates the signature size
		//
		if (SGX_RSA3072_KEY_SIZE != siglen) {
			break;
		}

		retval = SGX_SUCCESS;
	} while (0);

	if (retval != SGX_SUCCESS) {
		GET_LAST_OPENSSL_ERROR;
	}

	if (ctx)
		EVP_MD_CTX_free(ctx);
	if (priv_pkey) {
		EVP_PKEY_free(priv_pkey);
		priv_rsa_key = NULL;
		n = NULL;
		d = NULL;
		e = NULL;
	}
	if (priv_rsa_key) {
		RSA_free(priv_rsa_key);
		n = NULL;
		d = NULL;
		e = NULL;
	}
	if (n)
		BN_clear_free(n);
	if (d)
		BN_clear_free(d);
	if (e)
		BN_clear_free(e);

	return retval;
}
Esempio n. 13
0
int main()
{
	int ret = -1;
	int verbose = 0;
	BIO *out = NULL;

	int id = EVP_PKEY_SM2;
	const EVP_MD *md = EVP_sm3();
	ENGINE *engine = NULL;

	EVP_PKEY_CTX *pkctx = NULL;
	EVP_PKEY *pkey = NULL;
	EVP_MD_CTX *mdctx = NULL;
	EVP_CIPHER_CTX *cpctx = NULL;

	unsigned char dgst[EVP_MAX_MD_SIZE] = "hello world";
	size_t dgstlen = 32;
	unsigned char sig[256];
	size_t siglen = sizeof(sig);

	unsigned char msg[] = "hello world this is the message";
	size_t msglen = sizeof(msg);
	unsigned char cbuf[512];
	size_t cbuflen = sizeof(cbuf);
	unsigned char mbuf[512];
	size_t mbuflen = sizeof(mbuf);

	int len;
	unsigned int ulen;

	ERR_load_crypto_strings();

	out = BIO_new_fp(stdout, BIO_NOCLOSE);

	if (!(pkctx = EVP_PKEY_CTX_new_id(id, engine))) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_PKEY_keygen_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_PKEY_keygen(pkctx, &pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	EVP_PKEY_CTX_free(pkctx);

	if (0) {
		EVP_PKEY_print_public(out, pkey, 4, NULL);
		BIO_printf(out, "\n");
		EVP_PKEY_print_private(out, pkey, 4, NULL);
		BIO_printf(out, "\n");
	}

	if (!(pkctx = EVP_PKEY_CTX_new(pkey, engine))) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	/* EVP_PKEY_sign() */

	if (!EVP_PKEY_sign_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	bzero(sig, sizeof(sig));
	siglen = sizeof(sig);
	dgstlen = 32;

	if (!EVP_PKEY_sign(pkctx, sig, &siglen, dgst, dgstlen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		size_t i;
		printf("signature (%zu bytes) = ", siglen);
		for (i = 0; i < siglen; i++) {
			printf("%02X", sig[i]);
		}
		printf("\n");
	}

	if (!EVP_PKEY_verify_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (EVP_PKEY_verify(pkctx, sig, siglen, dgst, dgstlen) != SM2_VERIFY_SUCCESS) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("signature verification success!\n");
	}

	/* EVP_PKEY_encrypt() */

	if (!EVP_PKEY_encrypt_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	cbuflen = sizeof(cbuf);
	if (!EVP_PKEY_encrypt(pkctx, cbuf, &cbuflen, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		size_t i;
		printf("ciphertext (%zu bytes) = ", cbuflen);
		for (i = 0; i < cbuflen; i++) {
			printf("%02X", cbuf[i]);
		}
		printf("\n");
	}

	if (!EVP_PKEY_decrypt_init(pkctx)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	bzero(mbuf, sizeof(mbuf));
	mbuflen = sizeof(mbuf);
	if (!EVP_PKEY_decrypt(pkctx, mbuf, &mbuflen, cbuf, cbuflen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("original  message = %s\n", msg);
		printf("decrypted message = %s\n", mbuf);
	}


	/* EVP_PKEY_encrypt_old */


	if ((len = EVP_PKEY_encrypt_old(cbuf, msg, (int)msglen, pkey)) <= 0) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		int i;
		printf("ciphertext (%d bytes) = ", len);
		for (i = 0; i < len; i++) {
			printf("%02X", cbuf[i]);
		}
		printf("\n");
	}

	bzero(mbuf, sizeof(mbuf));
	if ((len = EVP_PKEY_decrypt_old(mbuf, cbuf, len, pkey)) <= 0) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (verbose) {
		printf("original  message = %s\n", msg);
		printf("decrypted message = %s\n", mbuf);
	}

	if (!(mdctx = EVP_MD_CTX_create())) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	
	/* EVP_SignInit_ex/Update/Final_ex */

	if (!EVP_SignInit_ex(mdctx, EVP_sm3(), engine)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_SignUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_SignFinal(mdctx, sig, &ulen, pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}
	siglen = ulen;

	if (verbose) {
		size_t i;
		printf("signature (%zu bytes) = ", siglen);
		for (i = 0; i < siglen; i++) {
			printf("%02X", sig[i]);
		}
		printf("\n");
	}

	if (!EVP_VerifyInit_ex(mdctx, EVP_sm3(), engine)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_VerifyUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (EVP_VerifyFinal(mdctx, sig, ulen, pkey) != SM2_VERIFY_SUCCESS) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}


	/* EVP_DigestSignInit/Update/Final() */
	// FIXME: return values might be different, not just 1 or 0
	if (!EVP_DigestSignInit(mdctx, &pkctx, md, engine, pkey)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestSignUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	siglen = sizeof(sig);
	if (!EVP_DigestSignFinal(mdctx, sig, &siglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	pkctx = NULL;	
	if (!EVP_DigestVerifyInit(mdctx, &pkctx, md, engine, pkey)) {
		ERR_print_errors_fp(stderr);
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestVerifyUpdate(mdctx, msg, msglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}

	if (!EVP_DigestVerifyFinal(mdctx, sig, siglen)) {
		fprintf(stderr, "error: %s %d\n", __FILE__, __LINE__);
		goto end;
	}


	/* EVP_SealInit/Update/Final() EVP_OpenInit/Update/Final() */
	/*
	EVP_PKEY *pk[NUM_PKEYS] = {0};
	unsigned char iv[16];
	unsigned char ek[NUM_PKEYS][256];
	int eklen[NUM_PKEYS];

	RAND_pseudo_bytes(iv, sizeof(iv));

	int i;
	for (i = 0; i < NUM_PKEYS; i++) {
	}

	if (!(cpctx = EVP_CIPHER_CTX_new())) {
		goto end;
	}

	if (!EVP_SealInit(cpctx, cipher, ek, &ekl, iv, pubk, npubk)) {
		goto end;
	}

	if (!EVP_SealUpdate(cpctx, msg, msglen)) {
		goto end;
	}

	if (!EVP_SealFinal(cpctx, cbuf, (int *)&cbuflen)) {
		goto end;
	}
	*/

	printf("test success!\n");
	ret = 1;
end:
	ERR_print_errors_fp(stderr);
	return ret;
}
static char *ngx_http_acme_sign_json(ngx_conf_t *cf, void *conf, json_t *payload, RSA *key, ngx_str_t replay_nonce, json_t **flattened_jws)
{
    /*
     * Structure according to RFC7515:
     *
     * {
     *  "payload":"<payload contents>",
     *  "protected":"<integrity-protected header contents>",
     *  "header":<non-integrity-protected header contents>,
     *  "signature":"<signature contents>"
     * }
     *
     * Example:
     *
     * {
     *  "payload":
     *   "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
     *  "protected":"eyJhbGciOiJFUzI1NiJ9",
     *  "header": {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
     *  "signature":
     *   "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q"
     * }
     */

    /*
     * ACME restrictions:
     * The JWS MUST use the Flattened JSON Serialization
     * The JWS MUST be encoded using UTF-8
     * The JWS Header or Protected Header MUST include “alg” and “jwk” fields
     * The JWS MUST NOT have the value “none” in its “alg” field
     */

    json_t *jwk;
    json_t *header;
    ngx_str_t encoded_protected_header, serialized_payload, encoded_payload, tmp;
    ngx_str_t signing_input, signature, encoded_signature;
    u_char *tmp_char_p;

    /* Variables for signing */
    EVP_PKEY *evp_key;
    EVP_MD_CTX *mdctx = NULL;
    int ret = 0;

    /*
     * Encode payload
     */

    serialized_payload = (ngx_str_t)ngx_string_dynamic(json_dumps(payload, 0));
    encoded_payload.len = ngx_base64_encoded_length(serialized_payload.len);
    encoded_payload.data = ngx_alloc(encoded_payload.len, cf->log);
    ngx_encode_base64url(&encoded_payload, &serialized_payload);

    println_debug("Signing payload: ", &serialized_payload);

    /*
     * Create header
     */

    /* jwk header */
    if(ngx_http_acme_create_jwk(cf, conf, key, &jwk) != NGX_CONF_OK) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Failed to create the JWK from the account key");
        ngx_free(serialized_payload.data);
        ngx_free(encoded_payload.data);
        return NGX_CONF_ERROR;
    }

    /* Pack header into JSON */
    header = json_pack("{s:s, s:s%, s:o}", "alg", "RS256", "nonce", replay_nonce.data, replay_nonce.len, "jwk", jwk);
    if(header == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error packing JWS header");
        ngx_free(serialized_payload.data);
        ngx_free(encoded_payload.data);
        return NGX_CONF_ERROR;
    }

    /* Serialize and base64url encode header */
    tmp = (ngx_str_t)ngx_string_dynamic(json_dumps(header, 0));
    encoded_protected_header.len = ngx_base64_encoded_length(tmp.len);
    encoded_protected_header.data = ngx_alloc(encoded_protected_header.len, cf->log);
    ngx_encode_base64url(&encoded_protected_header, &tmp);
    ngx_free(tmp.data);
    json_decref(header);

    /*
     * Create signature
     */

    /* Create signing input */
    /* = ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) */
    signing_input.len = encoded_protected_header.len + strlen(".") + encoded_payload.len;
    signing_input.data = ngx_alloc(signing_input.len, cf->log);
    tmp_char_p = ngx_copy(signing_input.data, encoded_protected_header.data, encoded_protected_header.len);
    tmp_char_p = ngx_copy(tmp_char_p, ".", strlen("."));
    tmp_char_p = ngx_copy(tmp_char_p, encoded_payload.data, encoded_payload.len);

    /* Convert the RSA key to the EVP_PKEY structure */
    evp_key = EVP_PKEY_new();
    if(evp_key == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature.");
        return NGX_CONF_ERROR;
    }

    if(EVP_PKEY_set1_RSA(evp_key, key) == 0) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature.");
        return NGX_CONF_ERROR;
    }

    /* Create the message digest context */
    ret = 0;
    mdctx = EVP_MD_CTX_create();
    if(mdctx == NULL)
        goto err;

    /* Initialize the DigestSign operation - SHA-256 has been selected as the message digest function */
    if(EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, evp_key) != 1)
        goto err;

    /* Call update with the message */
    if(EVP_DigestSignUpdate(mdctx, signing_input.data, signing_input.len) != 1)
        goto err;

    /* Finalise the DigestSign operation */
    /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the */
    /* signature. The length is returned in siglen. */
    if(EVP_DigestSignFinal(mdctx, NULL, &signature.len) != 1)
        goto err;

    /* Allocate memory for the signature */
    signature.data = ngx_alloc(signature.len, cf->log);

    /* Obtain the signature */
    if(EVP_DigestSignFinal(mdctx, signature.data, &signature.len) != 1)
        goto err;

    /* Success */
    ret = 1;

    err:
    if(ret != 1) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "Error signing the message digest for the JWS signature. OpenSSL error 0x%xl", ERR_get_error());
        return NGX_CONF_ERROR;
    }

    /* Clean up */
    EVP_MD_CTX_destroy(mdctx);
    EVP_PKEY_free(evp_key);

    /* base64url encode the signature */
    encoded_signature.len = ngx_base64_encoded_length(signature.len);
    encoded_signature.data = ngx_alloc(encoded_signature.len, cf->log);
    ngx_encode_base64url(&encoded_signature, &signature);
    ngx_free(signature.data);

    /*
     * Create flattened JWS serialization
     */

    *flattened_jws = json_pack("{s:s%,s:s%,s:s%}",
            "payload", encoded_payload.data, encoded_payload.len,
            "protected", encoded_protected_header.data, encoded_protected_header.len,
            "signature", encoded_signature.data, encoded_signature.len
            );

    ngx_free(serialized_payload.data);
    // TODO (KK) Maybe this is too early for a free since the strings will be used in the flattened JWS (but when to free then?)
    ngx_free(encoded_payload.data);
    ngx_free(encoded_protected_header.data);
    ngx_free(encoded_signature.data);

    if(*flattened_jws == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error serializing flattened JWS");
        return NGX_CONF_ERROR;
    }


    return NGX_CONF_OK;
} /* ngx_http_acme_sign_json */
Esempio n. 15
0
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
                       X509_ALGOR *algor1, X509_ALGOR *algor2,
                       ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
    const EVP_MD *type;
    EVP_PKEY *pkey;
    unsigned char *buf_in = NULL, *buf_out = NULL;
    size_t inl = 0, outl = 0, outll = 0;
    int signid, paramtype;
    int rv;

    type = EVP_MD_CTX_md(ctx);
    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

    if (!type || !pkey) {
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
        return 0;
    }

    if (pkey->ameth->item_sign) {
        rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
        if (rv == 1)
            outl = signature->length;
        /*-
         * Return value meanings:
         * <=0: error.
         *   1: method does everything.
         *   2: carry on as normal.
         *   3: ASN1 method sets algorithm identifiers: just sign.
         */
        if (rv <= 0)
            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        if (rv <= 1)
            goto err;
    } else
        rv = 2;

    if (rv == 2) {
        if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
            if (!pkey->ameth ||
                !OBJ_find_sigid_by_algs(&signid,
                                        EVP_MD_nid(type),
                                        pkey->ameth->pkey_id)) {
                ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
                        ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
                return 0;
            }
        } else
            signid = type->pkey_type;

        if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
            paramtype = V_ASN1_NULL;
        else
            paramtype = V_ASN1_UNDEF;

        if (algor1)
            X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
        if (algor2)
            X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

    }

    inl = ASN1_item_i2d(asn, &buf_in, it);
    outll = outl = EVP_PKEY_size(pkey);
    buf_out = OPENSSL_malloc((unsigned int)outl);
    if ((buf_in == NULL) || (buf_out == NULL)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        goto err;
    }

    if (signature->data != NULL)
        OPENSSL_free(signature->data);
    signature->data = buf_out;
    buf_out = NULL;
    signature->length = outl;
    /*
     * In the interests of compatibility, I'll make sure that the bit string
     * has a 'not-used bits' value of 0
     */
    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
 err:
    EVP_MD_CTX_cleanup(ctx);
    if (buf_in != NULL) {
        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
        OPENSSL_free(buf_in);
    }
    if (buf_out != NULL) {
        OPENSSL_cleanse((char *)buf_out, outll);
        OPENSSL_free(buf_out);
    }
    return (outl);
}
Esempio n. 16
0
static int tls1_prf_P_hash(const EVP_MD *md,
                           const unsigned char *sec, size_t sec_len,
                           const unsigned char *seed, size_t seed_len,
                           unsigned char *out, size_t olen)
{
    int chunk;
    EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
    EVP_PKEY *mac_key = NULL;
    unsigned char A1[EVP_MAX_MD_SIZE];
    size_t A1_len;
    int ret = 0;

    chunk = EVP_MD_size(md);
    if (!ossl_assert(chunk > 0))
        goto err;

    ctx = EVP_MD_CTX_new();
    ctx_tmp = EVP_MD_CTX_new();
    ctx_init = EVP_MD_CTX_new();
    if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
        goto err;
    EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
    mac_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
    if (mac_key == NULL)
        goto err;
    if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
        goto err;
    if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
        goto err;
    if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
        goto err;
    if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
        goto err;

    for (;;) {
        /* Reinit mac contexts */
        if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
            goto err;
        if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
            goto err;
        if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
            goto err;
        if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
            goto err;

        if (olen > (size_t)chunk) {
            size_t mac_len;
            if (!EVP_DigestSignFinal(ctx, out, &mac_len))
                goto err;
            out += mac_len;
            olen -= mac_len;
            /* calc the next A1 value */
            if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
                goto err;
        } else {                /* last one */

            if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
                goto err;
            memcpy(out, A1, olen);
            break;
        }
    }
    ret = 1;
 err:
    EVP_PKEY_free(mac_key);
    EVP_MD_CTX_free(ctx);
    EVP_MD_CTX_free(ctx_tmp);
    EVP_MD_CTX_free(ctx_init);
    OPENSSL_cleanse(A1, sizeof(A1));
    return ret;
}
Esempio n. 17
0
/* seed1 through seed5 are virtually concatenated */
static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
			int sec_len,
			const void *seed1, int seed1_len,
			const void *seed2, int seed2_len,
			const void *seed3, int seed3_len,
			const void *seed4, int seed4_len,
			const void *seed5, int seed5_len,
			unsigned char *out, int olen)
	{
	int chunk;
	size_t j;
	EVP_MD_CTX ctx, ctx_tmp;
	EVP_PKEY *mac_key;
	unsigned char A1[EVP_MAX_MD_SIZE];
	size_t A1_len;
	int ret = 0;
	
	chunk=EVP_MD_size(md);
	OPENSSL_assert(chunk >= 0);

	EVP_MD_CTX_init(&ctx);
	EVP_MD_CTX_init(&ctx_tmp);
	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	EVP_MD_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
	if (!mac_key)
		goto err;
	if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
		goto err;
	if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
		goto err;
	if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
		goto err;
	if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
		goto err;
	if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
		goto err;
	if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
		goto err;
	if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
		goto err;
	if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
		goto err;

	for (;;)
		{
		/* Reinit mac contexts */
		if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx_tmp,A1,A1_len))
			goto err;
		if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
			goto err;
		if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
			goto err;
		if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
			goto err;
		if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
			goto err;
		if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
			goto err;

		if (olen > chunk)
			{
			if (!EVP_DigestSignFinal(&ctx,out,&j))
				goto err;
			out+=j;
			olen-=j;
			/* calc the next A1 value */
			if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len))
				goto err;
			}
		else	/* last one */
			{
			if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
				goto err;
			memcpy(out,A1,olen);
			break;
			}
		}
	ret = 1;
err:
	EVP_PKEY_free(mac_key);
	EVP_MD_CTX_cleanup(&ctx);
	EVP_MD_CTX_cleanup(&ctx_tmp);
	OPENSSL_cleanse(A1,sizeof(A1));
	return ret;
	}
/**
 *
 * \brief Generates a digest then sends the digest to the
 *        ATECCX08 chip to generate an ECDSA signature using
 *        private key from TLS_SLOT_AUTH_PRIV slot. The private
 *        key is always stays in the chip: OpenSSL (nor any
 *        other software) has no way to read it.
 *
 * \param[in] ctx - a pointer to the EVP_MD_CTX structure
 * \param[in] it - a pointer to the ASN1_ITEM structure
 * \param[in] asn - a void pointer to the parameter
 * \param[in] algor1 - a pointer to the X509_ALGOR structure
 * \param[in] algor2 - a pointer to the X509_ALGOR structure
 * \param[out] signature - a pointer to the ASN1_BIT_STRING
 *       structure to return the signature in the ASN.1 format
 * \return 1 for success
 */
int eccx08_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                     X509_ALGOR *algor1, X509_ALGOR *algor2,
                     ASN1_BIT_STRING *signature)
{
    int rc = 0;
    int ret = 0;
    const EVP_MD *type;
    EVP_PKEY *pkey;
    uint8_t *buf_in = NULL, *buf_out = NULL;
    uint8_t *sig_in = NULL, *sig_out = NULL;
    size_t inl = 0, outl = 0, outll = 0;
    int signid, paramtype;
    uint8_t slotid = TLS_SLOT_AUTH_PRIV;
    ATCA_STATUS status = ATCA_GEN_FAIL;

    extern ECDSA_METHOD eccx08_ecdsa;

    type = EVP_MD_CTX_md(ctx);
    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

    if (!type || !pkey) {
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
        return 0;
    }

    if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
        if (!pkey->ameth ||
            !OBJ_find_sigid_by_algs(&signid,
                                    EVP_MD_nid(type),
                                    pkey->ameth->pkey_id)) {
            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
                    ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
            return 0;
        }
    } else signid = type->pkey_type;

    if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) paramtype = V_ASN1_NULL;
    else paramtype = V_ASN1_UNDEF;

    if (algor1) X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
    if (algor2) X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

    inl = ASN1_item_i2d(asn, &buf_in, it);
    outll = outl = EVP_PKEY_size(pkey);
    buf_out = OPENSSL_malloc((unsigned int)outl);
    if ((buf_in == NULL) || (buf_out == NULL)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
#ifdef USE_ECCX08
    eccx08_debug("eccx08_item_sign() - HW\n");

    ret = EVP_DigestUpdate(ctx, buf_in, inl);
    if (!ret) goto done;
    ret = EVP_DigestFinal(ctx, buf_out, (unsigned int *)&outl);
    if (!ret) goto done;
    sig_in = OPENSSL_malloc((unsigned int)outll);  // source of crash
    sig_out = sig_in;
    if (sig_in == NULL) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
    ECDSA_SIG *ecdsasig;
    ecdsasig = eccx08_ecdsa.ecdsa_do_sign(buf_out, outl, NULL, NULL, pkey->pkey.ec);
    if (ecdsasig == NULL) goto done;
    outl = i2d_ECDSA_SIG(ecdsasig, &sig_in);
    if (ecdsasig->r) {
        BN_free(ecdsasig->r);
        ecdsasig->r = NULL;
    }
    if (ecdsasig->s) {
        BN_free(ecdsasig->s);
        ecdsasig->s = NULL;
    }
    ECDSA_SIG_free(ecdsasig);

#else // USE_ECCX08
    eccx08_debug("eccx08_item_sign() - SW\n");
    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        goto done;
    }
#endif // USE_ECCX08
    if (signature->data != NULL) {
        OPENSSL_free(signature->data);
    }
#ifdef USE_ECCX08
    signature->data = sig_out;
    sig_out = NULL;
#else
    signature->data = buf_out;
    buf_out = NULL;
#endif
    signature->length = outl;
    /* 
     * ASN1_item_sign_ctx() in a_sign.c comment (just copy it here): 
     * In the interests of compatibility, I'll make sure that the bit string
     * has a 'not-used bits' value of 0
     */
    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;

    rc = 1;
done:
    EVP_MD_CTX_cleanup(ctx);
    if (buf_in != NULL) {
        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
        OPENSSL_free(buf_in);
    }
    if (buf_out != NULL) {
        OPENSSL_cleanse((char *)buf_out, outll);
        OPENSSL_free(buf_out);
    }
    if (sig_out != NULL) {
        OPENSSL_cleanse((char *)sig_out, outll);
        OPENSSL_free(sig_out);
    }
    return (rc);
}
Esempio n. 19
0
static int test_EVP_SM2(void)
{
    int ret = 0;
    EVP_PKEY *pkey = NULL;
    EVP_PKEY *params = NULL;
    EVP_PKEY_CTX *pctx = NULL;
    EVP_PKEY_CTX *kctx = NULL;
    EVP_PKEY_CTX *sctx = NULL;
    size_t sig_len = 0;
    unsigned char *sig = NULL;
    EVP_MD_CTX *md_ctx = NULL;
    EVP_MD_CTX *md_ctx_verify = NULL;
    EVP_PKEY_CTX *cctx = NULL;

    uint8_t ciphertext[128];
    size_t ctext_len = sizeof(ciphertext);

    uint8_t plaintext[8];
    size_t ptext_len = sizeof(plaintext);

    uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'};

    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
    if (!TEST_ptr(pctx))
        goto done;

    if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1))
        goto done;

    if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2)))
        goto done;

    if (!TEST_true(EVP_PKEY_paramgen(pctx, &params)))
        goto done;

    kctx = EVP_PKEY_CTX_new(params, NULL);
    if (!TEST_ptr(kctx))
        goto done;

    if (!TEST_true(EVP_PKEY_keygen_init(kctx)))
        goto done;

    if (!TEST_true(EVP_PKEY_keygen(kctx, &pkey)))
        goto done;

    if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)))
        goto done;

    if (!TEST_ptr(md_ctx = EVP_MD_CTX_new()))
        goto done;

    if (!TEST_ptr(md_ctx_verify = EVP_MD_CTX_new()))
        goto done;

    if (!TEST_ptr(sctx = EVP_PKEY_CTX_new(pkey, NULL)))
        goto done;

    EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx);
    EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx);

    if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0))
        goto done;

    if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey)))
        goto done;

    if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))))
        goto done;

    /* Determine the size of the signature. */
    if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len)))
        goto done;

    if (!TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey)))
        goto done;

    if (!TEST_ptr(sig = OPENSSL_malloc(sig_len)))
        goto done;

    if (!TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len)))
        goto done;

    /* Ensure that the signature round-trips. */

    if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey)))
        goto done;

    if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg))))
        goto done;

    if (!TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len)))
        goto done;

    /* now check encryption/decryption */

    if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL)))
        goto done;

    if (!TEST_true(EVP_PKEY_encrypt_init(cctx)))
        goto done;

    if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg))))
        goto done;

    if (!TEST_true(EVP_PKEY_decrypt_init(cctx)))
        goto done;

    if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len)))
        goto done;

    if (!TEST_true(ptext_len == sizeof(kMsg)))
        goto done;

    if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0))
        goto done;

    ret = 1;
done:
    EVP_PKEY_CTX_free(pctx);
    EVP_PKEY_CTX_free(kctx);
    EVP_PKEY_CTX_free(sctx);
    EVP_PKEY_CTX_free(cctx);
    EVP_PKEY_free(pkey);
    EVP_PKEY_free(params);
    EVP_MD_CTX_free(md_ctx);
    EVP_MD_CTX_free(md_ctx_verify);
    OPENSSL_free(sig);
    return ret;
}
Esempio n. 20
0
static int s2n_evp_hmac_p_hash_update(struct s2n_prf_working_space *ws, const void *data, uint32_t size)
{
    GUARD_OSSL(EVP_DigestSignUpdate(ws->tls.p_hash.evp_hmac.evp_digest.ctx, data, (size_t)size), S2N_ERR_P_HASH_UPDATE_FAILED);

    return 0;
}
Esempio n. 21
0
int jwt_sign_sha_pem(jwt_t *jwt, char **out, unsigned int *len,
		     const char *str)
{
	EVP_MD_CTX *mdctx = NULL;
	ECDSA_SIG *ec_sig = NULL;
	const BIGNUM *ec_sig_r = NULL;
	const BIGNUM *ec_sig_s = NULL;
	BIO *bufkey = NULL;
	const EVP_MD *alg;
	int type;
	EVP_PKEY *pkey = NULL;
	int pkey_type;
	unsigned char *sig;
	int ret = 0;
	size_t slen;

	switch (jwt->alg) {
	/* RSA */
	case JWT_ALG_RS256:
		alg = EVP_sha256();
		type = EVP_PKEY_RSA;
		break;
	case JWT_ALG_RS384:
		alg = EVP_sha384();
		type = EVP_PKEY_RSA;
		break;
	case JWT_ALG_RS512:
		alg = EVP_sha512();
		type = EVP_PKEY_RSA;
		break;

	/* ECC */
	case JWT_ALG_ES256:
		alg = EVP_sha256();
		type = EVP_PKEY_EC;
		break;
	case JWT_ALG_ES384:
		alg = EVP_sha384();
		type = EVP_PKEY_EC;
		break;
	case JWT_ALG_ES512:
		alg = EVP_sha512();
		type = EVP_PKEY_EC;
		break;

	default:
		return EINVAL;
	}

	bufkey = BIO_new_mem_buf(jwt->key, jwt->key_len);
	if (bufkey == NULL)
		SIGN_ERROR(ENOMEM);

	/* This uses OpenSSL's default passphrase callback if needed. The
	 * library caller can override this in many ways, all of which are
	 * outside of the scope of LibJWT and this is documented in jwt.h. */
	pkey = PEM_read_bio_PrivateKey(bufkey, NULL, NULL, NULL);
	if (pkey == NULL)
		SIGN_ERROR(EINVAL);

	pkey_type = EVP_PKEY_id(pkey);
	if (pkey_type != type)
		SIGN_ERROR(EINVAL);

	mdctx = EVP_MD_CTX_create();
	if (mdctx == NULL)
		SIGN_ERROR(ENOMEM);

	/* Initialize the DigestSign operation using alg */
	if (EVP_DigestSignInit(mdctx, NULL, alg, NULL, pkey) != 1)
		SIGN_ERROR(EINVAL);

	/* Call update with the message */
	if (EVP_DigestSignUpdate(mdctx, str, strlen(str)) != 1)
		SIGN_ERROR(EINVAL);

	/* First, call EVP_DigestSignFinal with a NULL sig parameter to get length
	 * of sig. Length is returned in slen */
	if (EVP_DigestSignFinal(mdctx, NULL, &slen) != 1)
		SIGN_ERROR(EINVAL);

	/* Allocate memory for signature based on returned size */
	sig = alloca(slen);
	if (sig == NULL)
		SIGN_ERROR(ENOMEM);

	/* Get the signature */
	if (EVP_DigestSignFinal(mdctx, sig, &slen) != 1)
		SIGN_ERROR(EINVAL);

	if (pkey_type != EVP_PKEY_EC) {
		*out = malloc(slen);
		if (*out == NULL)
			SIGN_ERROR(ENOMEM);
		memcpy(*out, sig, slen);
		*len = slen;
	} else {
		unsigned int degree, bn_len, r_len, s_len, buf_len;
		unsigned char *raw_buf;
		EC_KEY *ec_key;

		/* For EC we need to convert to a raw format of R/S. */

		/* Get the actual ec_key */
		ec_key = EVP_PKEY_get1_EC_KEY(pkey);
		if (ec_key == NULL)
			SIGN_ERROR(ENOMEM);

		degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key));

		EC_KEY_free(ec_key);

		/* Get the sig from the DER encoded version. */
		ec_sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&sig, slen);
		if (ec_sig == NULL)
			SIGN_ERROR(ENOMEM);

		ECDSA_SIG_get0(ec_sig, &ec_sig_r, &ec_sig_s);
		r_len = BN_num_bytes(ec_sig_r);
		s_len = BN_num_bytes(ec_sig_s);
		bn_len = (degree + 7) / 8;
		if ((r_len > bn_len) || (s_len > bn_len))
			SIGN_ERROR(EINVAL);

		buf_len = 2 * bn_len;
		raw_buf = alloca(buf_len);
		if (raw_buf == NULL)
			SIGN_ERROR(ENOMEM);

		/* Pad the bignums with leading zeroes. */
		memset(raw_buf, 0, buf_len);
		BN_bn2bin(ec_sig_r, raw_buf + bn_len - r_len);
		BN_bn2bin(ec_sig_s, raw_buf + buf_len - s_len);

		*out = malloc(buf_len);
		if (*out == NULL)
			SIGN_ERROR(ENOMEM);
		memcpy(*out, raw_buf, buf_len);
		*len = buf_len;
	}

jwt_sign_sha_pem_done:
	if (bufkey)
		BIO_free(bufkey);
	if (pkey)
		EVP_PKEY_free(pkey);
	if (mdctx)
		EVP_MD_CTX_destroy(mdctx);
	if (ec_sig)
		ECDSA_SIG_free(ec_sig);

	return ret;
}
Esempio n. 22
0
int sign_it(const byte* msg, size_t mlen, byte** sig, size_t* slen, EVP_PKEY* pkey)
{
    /* Returned to caller */
    int result = -1;
    
    if(!msg || !mlen || !sig || !pkey) {
        assert(0);
        return -1;
    }
    
    if(*sig)
        OPENSSL_free(*sig);
    
    *sig = NULL;
    *slen = 0;
    
    EVP_MD_CTX* ctx = NULL;
    
    do
    {
        ctx = EVP_MD_CTX_create();
        assert(ctx != NULL);
        if(ctx == NULL) {
            printf("EVP_MD_CTX_create failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        const EVP_MD* md = EVP_get_digestbyname(hn);
        assert(md != NULL);
        if(md == NULL) {
            printf("EVP_get_digestbyname failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        int rc = EVP_DigestInit_ex(ctx, md, NULL);
        assert(rc == 1);
        if(rc != 1) {
            printf("EVP_DigestInit_ex failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey);
        assert(rc == 1);
        if(rc != 1) {
            printf("EVP_DigestSignInit failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        rc = EVP_DigestSignUpdate(ctx, msg, mlen);
        assert(rc == 1);
        if(rc != 1) {
            printf("EVP_DigestSignUpdate failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        size_t req = 0;
        rc = EVP_DigestSignFinal(ctx, NULL, &req);
        assert(rc == 1);
        if(rc != 1) {
            printf("EVP_DigestSignFinal failed (1), error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        assert(req > 0);
        if(!(req > 0)) {
            printf("EVP_DigestSignFinal failed (2), error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        *sig = OPENSSL_malloc(req);
        assert(*sig != NULL);
        if(*sig == NULL) {
            printf("OPENSSL_malloc failed, error 0x%lx\n", ERR_get_error());
            break; /* failed */
        }
        
        *slen = req;
        rc = EVP_DigestSignFinal(ctx, *sig, slen);
        assert(rc == 1);
        if(rc != 1) {
            printf("EVP_DigestSignFinal failed (3), return code %d, error 0x%lx\n", rc, ERR_get_error());
            break; /* failed */
        }
        
        assert(req == *slen);
        if(rc != 1) {
            printf("EVP_DigestSignFinal failed, mismatched signature sizes %ld, %ld", req, *slen);
            break; /* failed */
        }
        
        result = 0;
        
    } while(0);
    
    if(ctx) {
        EVP_MD_CTX_destroy(ctx);
        ctx = NULL;
    }
    
    return !!result;
}
Esempio n. 23
0
int process_files(char **parameters, int param_count){
	int i, success = 0;
	size_t siglen;
	long int filesize=0, bytes_written=0;
	unsigned char *signature, *file_mem;
	char *boincname, *filename;
	EVP_MD_CTX *mdctx = NULL;
	FILE *current_file;
	BIO *b64, *bio_out;
	printf("Boinc filename     Filename           Status\n");
	printf("--------------------------------------------------------\n");
	for(i = 0; i<param_count; i+=2){
		boincname = parameters[i];
		filename = parameters[i+1];
		printf("%-18.18s %-18.18s ", boincname, filename);
		if(!(mdctx = EVP_MD_CTX_create())) goto err;

		if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, private_key)) goto err;

		/* Open file and get size */
		current_file = fopen(filename, "rb");
		if(current_file == NULL)
			{print_error("file_signing", "unable to open file", filename); goto err;}
		fseek(current_file, 0L, SEEK_END);
		filesize = ftell(current_file);
		file_mem = (unsigned char *)OPENSSL_malloc(filesize);
		if(file_mem == NULL)
			{print_error("file_signing", "unable to reserve memory for file", filename); goto err;}
		fseek(current_file, 0L, SEEK_SET);	//rewind to beginning of file

		/* read file to memory */
		bytes_written = fread(file_mem, 1, filesize, current_file);

		if(bytes_written != filesize){
			if(ferror(current_file))
				{print_error("file_signing", "Error reading file", filename); goto err;}
			else if(feof(current_file))
				{printf("File: %s wrote %li of filesize %li", filename, bytes_written, filesize); goto err;}
			else
				{print_error("file_signing", "something strange happened", filename); goto err;}
		}

		if(1 != EVP_DigestSignUpdate(mdctx, file_mem, filesize)) goto err;

		if(1 != EVP_DigestSignFinal(mdctx, NULL, &siglen)) goto err; // Get signature size

		if(!(signature = OPENSSL_malloc(sizeof(unsigned char) * siglen))) goto err;

		if(1 != EVP_DigestSignFinal(mdctx, signature, &siglen)) goto err;
		fwrite(boincname, sizeof(char), strlen(boincname), outputfile);
		fputc(' ', outputfile);
		b64 = BIO_new(BIO_f_base64());
		bio_out = BIO_new_fp(outputfile, BIO_NOCLOSE);
		BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
		BIO_push(b64, bio_out);
		BIO_write(b64, signature, sizeof(unsigned char) * siglen);
		BIO_flush(b64);
		BIO_free_all(b64);
		fputc('\n', outputfile);

		success = 1;

		printf("%-18.18s\n", "Success!");

		err:
		if(mdctx) EVP_MD_CTX_destroy(mdctx);
		if(current_file) fclose(current_file);
		if(file_mem) OPENSSL_free(file_mem);
		if(signature) OPENSSL_free(signature);
		if(!success)
			printf("%-18.18s\n", "Failed!");
	}
}
Esempio n. 24
0
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;
}