示例#1
0
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
                        size_t *out_sig_len) {
  int r = 0;
  const int has_signctx = ctx->pctx->pmeth->signctx != NULL;

  if (out_sig) {
    EVP_MD_CTX tmp_ctx;
    uint8_t md[EVP_MAX_MD_SIZE];
    unsigned int mdlen;

    EVP_MD_CTX_init(&tmp_ctx);
    if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) {
      return 0;
    }
    if (has_signctx) {
      r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx, out_sig, out_sig_len, &tmp_ctx);
    } else {
      r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
    }
    EVP_MD_CTX_cleanup(&tmp_ctx);
    if (has_signctx || !r) {
      return r;
    }
    return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
  } else {
    if (has_signctx) {
      return ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx);
    } else {
      size_t s = EVP_MD_size(ctx->digest);
      return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
    }
  }
}
示例#2
0
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                        size_t *siglen)
{
    int sctx = 0, r = 0;
    EVP_PKEY_CTX *pctx = ctx->pctx;
    if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
        if (!sigret)
            return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
            r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
        else {
            EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx);
            if (!dctx)
                return 0;
            r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
            EVP_PKEY_CTX_free(dctx);
        }
        return r;
    }
    if (pctx->pmeth->signctx)
        sctx = 1;
    else
        sctx = 0;
    if (sigret) {
        unsigned char md[EVP_MAX_MD_SIZE];
        unsigned int mdlen = 0;
        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
            if (sctx)
                r = ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx);
            else
                r = EVP_DigestFinal_ex(ctx, md, &mdlen);
        } else {
            EVP_MD_CTX tmp_ctx;
            EVP_MD_CTX_init(&tmp_ctx);
            if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx))
                return 0;
            if (sctx)
                r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
                                                 sigret, siglen, &tmp_ctx);
            else
                r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
            EVP_MD_CTX_cleanup(&tmp_ctx);
        }
        if (sctx || !r)
            return r;
        if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
            return 0;
    } else {
        if (sctx) {
            if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
                return 0;
        } else {
            int s = EVP_MD_size(ctx->digest);
            if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
                return 0;
        }
    }
    return 1;
}
示例#3
0
int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
                  unsigned int *out_sig_len, EVP_PKEY *pkey) {
  uint8_t m[EVP_MAX_MD_SIZE];
  unsigned int m_len;
  int ret = 0;
  EVP_MD_CTX tmp_ctx;
  EVP_PKEY_CTX *pkctx = NULL;
  size_t sig_len = EVP_PKEY_size(pkey);

  *out_sig_len = 0;
  EVP_MD_CTX_init(&tmp_ctx);
  if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
      !EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
    goto out;
  }
  EVP_MD_CTX_cleanup(&tmp_ctx);

  pkctx = EVP_PKEY_CTX_new(pkey, NULL);
  if (!pkctx || !EVP_PKEY_sign_init(pkctx) ||
      !EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) ||
      !EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) {
    goto out;
  }
  *out_sig_len = sig_len;
  ret = 1;

out:
  if (pkctx) {
    EVP_PKEY_CTX_free(pkctx);
  }

  return ret;
}
示例#4
0
文件: ssl_rsa.c 项目: a397871706/plug
enum ssl_private_key_result_t ssl_private_key_sign(
    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) {
  if (ssl->cert->key_method != NULL) {
    return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in,
                                       in_len);
  }

  enum ssl_private_key_result_t ret = ssl_private_key_failure;
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
  if (ctx == NULL) {
    goto end;
  }

  size_t len = max_out;
  if (!EVP_PKEY_sign_init(ctx) ||
      !EVP_PKEY_CTX_set_signature_md(ctx, md) ||
      !EVP_PKEY_sign(ctx, out, &len, in, in_len)) {
    goto end;
  }
  *out_len = len;
  ret = ssl_private_key_success;

end:
  EVP_PKEY_CTX_free(ctx);
  return ret;
}
示例#5
0
static int
do_keyop(EVP_PKEY_CTX * ctx, int pkey_op,
    unsigned char *out, size_t * poutlen,
    unsigned char *in, size_t inlen)
{
	int rv = 0;
	switch (pkey_op) {
	case EVP_PKEY_OP_VERIFYRECOVER:
		rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen);
		break;

	case EVP_PKEY_OP_SIGN:
		rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen);
		break;

	case EVP_PKEY_OP_ENCRYPT:
		rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen);
		break;

	case EVP_PKEY_OP_DECRYPT:
		rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen);
		break;

	case EVP_PKEY_OP_DERIVE:
		rv = EVP_PKEY_derive(ctx, out, poutlen);
		break;

	}
	return rv;
}
示例#6
0
//Experimental function for signing data using a public key. Couldn't get it
//complete working. Seems to have problem with XDRed things
unsigned char *sign_data(char *data, size_t len, EVP_PKEY* key, int *sig_len) 
{
	EVP_PKEY_CTX *ctx;
	ctx = EVP_PKEY_CTX_new(key, NULL);
	EVP_PKEY_sign_init(ctx);
	EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
	EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256());

	EVP_PKEY_sign(ctx, NULL, sig_len, data, len); //determines the sig_len
	unsigned char * sig = OPENSSL_malloc(*sig_len);
	if(EVP_PKEY_sign(ctx, sig, sig_len, data, len <= 0)) {
		ssl_error("PKEY SIGN");
		sig = NULL;
	}
	return sig;
}
int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
	     EVP_PKEY *pkey)
	{
	unsigned char m[EVP_MAX_MD_SIZE];
	unsigned int m_len;
	int i,ok=0,v;
	EVP_MD_CTX tmp_ctx;

	*siglen=0;
	EVP_MD_CTX_init(&tmp_ctx);
	EVP_MD_CTX_copy_ex(&tmp_ctx,ctx);   
	EVP_DigestFinal_ex(&tmp_ctx,&(m[0]),&m_len);
	EVP_MD_CTX_cleanup(&tmp_ctx);

	if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
		{
		EVP_PKEY_CTX *pkctx = NULL;
		size_t sltmp = (size_t)EVP_PKEY_size(pkey);
		i = 0;
		pkctx = EVP_PKEY_CTX_new(pkey, NULL);
		if (!pkctx)
			goto err;
		if (EVP_PKEY_sign_init(pkctx) <= 0)
			goto err;
		if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0)
			goto err;
		if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0)
			goto err;
		*siglen = sltmp;
		i = 1;
		err:
		EVP_PKEY_CTX_free(pkctx);
		return i;
		}

	for (i=0; i<4; i++)
		{
		v=ctx->digest->required_pkey_type[i];
		if (v == 0) break;
		if (pkey->type == v)
			{
			ok=1;
			break;
			}
		}
	if (!ok)
		{
		EVPerr(EVP_F_EVP_SIGNFINAL,EVP_R_WRONG_PUBLIC_KEY_TYPE);
		return(0);
		}

	if (ctx->digest->sign == NULL)
		{
		EVPerr(EVP_F_EVP_SIGNFINAL,EVP_R_NO_SIGN_FUNCTION_CONFIGURED);
		return(0);
		}
	return(ctx->digest->sign(ctx->digest->type,m,m_len,sigret,siglen,
		pkey->pkey.ptr));
	}
示例#8
0
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
	{
	int sctx, r = 0;
	if (ctx->pctx->pmeth->signctx)
		sctx = 1;
	else
		sctx = 0;
	if (sigret)
		{
		EVP_MD_CTX tmp_ctx;
		unsigned char md[EVP_MAX_MD_SIZE];
		unsigned int mdlen;
		EVP_MD_CTX_init(&tmp_ctx);
		if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
		     	return 0;
		if (sctx)
			r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
					sigret, siglen, &tmp_ctx);
		else
			r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
		EVP_MD_CTX_cleanup(&tmp_ctx);
		if (sctx || !r)
			return r;
		if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
			return 0;
		}
	else
		{
		if (sctx)
			{
			if (ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx) <= 0)
				return 0;
			}
		else
			{
			int s = EVP_MD_size(ctx->digest);
			if (s < 0 || EVP_PKEY_sign(ctx->pctx, sigret, siglen, NULL, s) <= 0)
				return 0;
			}
		}
	return 1;
	}
示例#9
0
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
                        size_t *out_sig_len) {
  if (out_sig) {
    EVP_MD_CTX tmp_ctx;
    int ret;
    uint8_t md[EVP_MAX_MD_SIZE];
    unsigned int mdlen;

    EVP_MD_CTX_init(&tmp_ctx);
    ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
          EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
          EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
    EVP_MD_CTX_cleanup(&tmp_ctx);

    return ret;
  } else {
    size_t s = EVP_MD_size(ctx->digest);
    return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
  }
}
示例#10
0
文件: p_sign.c 项目: AndreV84/openssl
int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                  unsigned int *siglen, EVP_PKEY *pkey)
{
    unsigned char m[EVP_MAX_MD_SIZE];
    unsigned int m_len = 0;
    int i = 0;
    size_t sltmp;
    EVP_PKEY_CTX *pkctx = NULL;

    *siglen = 0;
    if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_FINALISE)) {
        if (!EVP_DigestFinal_ex(ctx, m, &m_len))
            goto err;
    } else {
        int rv = 0;
        EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
        if (tmp_ctx == NULL) {
            EVPerr(EVP_F_EVP_SIGNFINAL, ERR_R_MALLOC_FAILURE);
            return 0;
        }
        rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
        if (rv)
            rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len);
        EVP_MD_CTX_free(tmp_ctx);
        if (!rv)
            return 0;
    }

    sltmp = (size_t)EVP_PKEY_size(pkey);
    i = 0;
    pkctx = EVP_PKEY_CTX_new(pkey, NULL);
    if (pkctx == NULL)
        goto err;
    if (EVP_PKEY_sign_init(pkctx) <= 0)
        goto err;
    if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0)
        goto err;
    if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0)
        goto err;
    *siglen = sltmp;
    i = 1;
 err:
    EVP_PKEY_CTX_free(pkctx);
    return i;
}
示例#11
0
文件: pki-x509.c 项目: rOpenSec/PKI
SEXP PKI_sign(SEXP what, SEXP sKey, SEXP sMD, SEXP sPad) {
    SEXP res;
    EVP_PKEY *key;
    EVP_PKEY_CTX *ctx;
    int mdt, padt, r;
    size_t sl;
    if (TYPEOF(what) != RAWSXP)
	Rf_error("invalid payload to sign - must be a raw vector");
    if (!inherits(sKey, "private.key"))
	Rf_error("key must be RSA private key");
    PKI_init();
    mdt = asInteger(sMD);
    padt = asInteger(sPad);
    key = (EVP_PKEY*) R_ExternalPtrAddr(sKey);
    if (!key)
	Rf_error("NULL key");
    ctx = EVP_PKEY_CTX_new(key);
    if (!ctx || EVP_PKEY_sign_init(ctx) <= 0)
	Rf_error("%s", ERR_error_string(ERR_get_error(), NULL));
    switch (padt) {
    case PKI_PKCS1:
    default:
	r = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
    }
    if (r <= 0)
	Rf_error("%s", ERR_error_string(ERR_get_error(), NULL));
    switch (mdt) {
    case PKI_MD5:
	r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_md5()); break;
    case PKI_SHA1:
	r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()); break;
    default:
    case PKI_SHA256:
	r = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()); break;
    }	
    if (r <= 0)
	Rf_error("%s", ERR_error_string(ERR_get_error(), NULL));
    sl = sizeof(buf);
    if (EVP_PKEY_sign(ctx, buf, &sl, (const unsigned char*) RAW(what), LENGTH(what)) <= 0)
	Rf_error("%s", ERR_error_string(ERR_get_error(), NULL));
    res = allocVector(RAWSXP, sl);
    memcpy(RAW(res), buf, sl);
    EVP_PKEY_CTX_free(ctx);
    return res;
}
static int sign_and_verify(int len)
{
    /*
     * Per FIPS 186-4, the hash is recommended to be the same length as q.
     * If the hash is longer than q, the leftmost N bits are used; if the hash
     * is shorter, then we left-pad (see appendix C.2.1).
     */
    size_t sigLength;
    int digestlen = BN_num_bytes(DSA_get0_q(dsakey));
    int ok = 0;

    unsigned char *dataToSign = OPENSSL_malloc(len);
    unsigned char *paddedData = OPENSSL_malloc(digestlen);
    unsigned char *signature = NULL;
    EVP_PKEY_CTX *ctx = NULL;
    EVP_PKEY *pkey = NULL;

    if (!TEST_ptr(dataToSign) ||
        !TEST_ptr(paddedData) ||
        !TEST_int_eq(RAND_bytes(dataToSign, len), 1))
        goto end;

    memset(paddedData, 0, digestlen);
    if (len > digestlen)
        memcpy(paddedData, dataToSign, digestlen);
    else
        memcpy(paddedData + digestlen - len, dataToSign, len);

    if (!TEST_ptr(pkey = EVP_PKEY_new()))
        goto end;
    EVP_PKEY_set1_DSA(pkey, dsakey);

    if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
        goto end;
    if (!TEST_int_eq(EVP_PKEY_sign_init(ctx), 1))
        goto end;

    if (EVP_PKEY_sign(ctx, NULL, &sigLength, dataToSign, len) != 1) {
        TEST_error("Failed to get signature length, len=%d", len);
        goto end;
    }

    if (!TEST_ptr(signature = OPENSSL_malloc(sigLength)))
        goto end;

    if (EVP_PKEY_sign(ctx, signature, &sigLength, dataToSign, len) != 1) {
        TEST_error("Failed to sign, len=%d", len);
        goto end;
    }

    /* Check that the signature is okay via the EVP interface */
    if (!TEST_int_eq(EVP_PKEY_verify_init(ctx), 1))
        goto end;

    /* ... using the same data we just signed */
    if (EVP_PKEY_verify(ctx, signature, sigLength, dataToSign, len) != 1) {
        TEST_error("EVP verify with unpadded length %d failed\n", len);
        goto end;
    }

    /* ... padding/truncating the data to the appropriate digest size */
    if (EVP_PKEY_verify(ctx, signature, sigLength, paddedData, digestlen) != 1) {
        TEST_error("EVP verify with length %d failed\n", len);
        goto end;
    }

    /* Verify again using the raw DSA interface */
    if (DSA_verify(0, dataToSign, len, signature, sigLength, dsakey) != 1) {
        TEST_error("Verification with unpadded data failed, len=%d", len);
        goto end;
    }

    if (DSA_verify(0, paddedData, digestlen, signature, sigLength, dsakey) != 1) {
        TEST_error("verify with length %d failed\n", len);
        goto end;
    }

    ok = 1;
end:
    EVP_PKEY_CTX_free(ctx);
    EVP_PKEY_free(pkey);

    OPENSSL_free(signature);
    OPENSSL_free(paddedData);
    OPENSSL_free(dataToSign);

    return ok;
}
示例#13
0
文件: utils.c 项目: zarelit/dgproto
uint8_t* sign(const char* keypath, const uint8_t* payload, const size_t plen, size_t* slen){

    FILE* ckeyfh;
    EVP_PKEY* ckey=NULL;
    EVP_PKEY_CTX* sigctx;
    uint8_t *sig;

    // Load signing key
    ckeyfh = fopen(keypath,"r");
    if(!ckeyfh)
    {
        fprintf(stderr, "%s: Cannot open the key file\n", __func__);
        sig = NULL;
        goto exit_sign;
    }
    ckey = PEM_read_PrivateKey(ckeyfh, &ckey, NULL, NULL);
    if(!ckey){
        fprintf(stderr,"Cannot read signing key from file %s\n", keypath);
        fclose(ckeyfh);
        sig = NULL;
        goto exit_sign;
    }

    // create signing context
    sigctx = EVP_PKEY_CTX_new(ckey, NULL);
    if (!sigctx){
        fprintf(stderr,"Cannot create a signing context\n");
        fclose(ckeyfh);
        sig = NULL;
        EVP_PKEY_free(ckey);
        goto exit_sign;
    }
    if (EVP_PKEY_sign_init(sigctx) <= 0){
        fprintf(stderr,"Cannot inizialize a signing context\n");
        sig = NULL;
        goto cleanup_sign;
    }

    // Ask the maximum signature size that will result in signing the payload
    if (EVP_PKEY_sign(sigctx, NULL, slen, payload, plen ) <= 0)
    {
        fprintf(stderr, "%s: Cannot get signature size\n", __func__);
        sig = NULL;
        goto cleanup_sign;
    }

    sig = malloc(*slen);
    if(!sig){
        fprintf(stderr,"Out of memory\n");
        goto cleanup_sign;
    }

    // Do the real signature
    if (EVP_PKEY_sign(sigctx, sig, slen, payload, plen) <= 0){
        ERR_load_crypto_strings();
        fprintf(stderr,"Signing operation failed\n");
        printf("%s\n", ERR_error_string(ERR_get_error(), NULL));
        ERR_free_strings();
        sig = NULL;
    }

cleanup_sign:
    fclose(ckeyfh);
    EVP_PKEY_CTX_free(sigctx);
    EVP_PKEY_free(ckey);

exit_sign:
    return sig;
}
示例#14
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;
}
示例#15
0
U8_EXPORT ssize_t u8_cryptic
(int do_encrypt,const char *cname,
 const unsigned char *key,int keylen,
 const unsigned char *iv,int ivlen,
 u8_block_reader reader,u8_block_writer writer,
 void *readstate,void *writestate,
 u8_context caller)
{
  if (strncasecmp(cname,"rsa",3)==0) {
    ENGINE *eng=ENGINE_get_default_RSA();
    EVP_PKEY _pkey, *pkey; EVP_PKEY_CTX *ctx; 
    int pubkeyin=(strncasecmp(cname,"rsapub",6)==0);
    const unsigned char *scankey=key;
    struct U8_BYTEBUF bb;
    int retval=-1;
    if (pubkeyin) pkey=d2i_PUBKEY(NULL,&scankey,keylen);
    else pkey=d2i_PrivateKey((EVP_PKEY_RSA),NULL,&scankey,keylen);
    if (!(pkey)) ctx=NULL;
    else {
#if (OPENSSL_VERSION_NUMBER>=0x1000204fL)
      ctx=EVP_PKEY_CTX_new(pkey,eng);
#else
      ctx=EVP_PKEY_CTX_new(pkey,NULL);
#endif
    }
    if (ctx) {
      memset(&bb,0,sizeof(bb));
      bb.u8_direction=u8_output_buffer;
      bb.u8_buf=bb.u8_ptr=(u8_byte *)u8_malloc(1024);
      bb.u8_lim=(u8_byte *)(bb.u8_buf+1024);
      bb.u8_growbuf=1;
      fill_bytebuf(&bb,reader,readstate);}
    if (!(ctx)) {}
    else if ((pubkeyin)?
	     ((do_encrypt)?((retval=EVP_PKEY_encrypt_init(ctx))<0):
	      ((retval=EVP_PKEY_verify_recover_init(ctx))<0)):
	     ((do_encrypt)?((retval=EVP_PKEY_sign_init(ctx))<0):
	      ((retval=EVP_PKEY_decrypt_init(ctx))<0))) {}
    else {
      unsigned char *in=bb.u8_buf; size_t inlen=bb.u8_ptr-bb.u8_buf;
      unsigned char *out=NULL; size_t outlen;
      if (pubkeyin) {
	if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,NULL,&outlen,in,inlen);
	else retval=EVP_PKEY_verify_recover(ctx,NULL,&outlen,in,inlen);}
      else if (do_encrypt) retval=EVP_PKEY_sign(ctx,NULL,&outlen,in,inlen);
      else retval=EVP_PKEY_decrypt(ctx,NULL,&outlen,in,inlen);
      if (retval<0) {}
      else if ((out=u8_malloc(outlen))==NULL) {}
      else if (pubkeyin) {
	if (do_encrypt) retval=EVP_PKEY_encrypt(ctx,out,&outlen,in,inlen);
	else retval=EVP_PKEY_verify_recover(ctx,out,&outlen,in,inlen);}
      else if (do_encrypt) retval=EVP_PKEY_sign(ctx,out,&outlen,in,inlen);
      else retval=EVP_PKEY_decrypt(ctx,out,&outlen,in,inlen);
      if (retval<0) {}
      else retval=writer(out,outlen,writestate);
      if (out) u8_free(out);}
    u8_free(bb.u8_buf);
    if (retval<0) {
      unsigned long err=ERR_get_error(); char buf[512];
      buf[0]='\0'; ERR_error_string_n(err,buf,512);
      u8_seterr(u8_InternalCryptoError,OPENSSL_CRYPTIC,u8_fromlibc((char *)buf));
      ERR_clear_error();}
    if (ctx) EVP_PKEY_CTX_free(ctx);
    if (pkey)  EVP_PKEY_free(pkey);
    return retval;}
  else {
    EVP_CIPHER_CTX ctx;
    int inlen, outlen, retval=0;
    ssize_t totalout=0, totalin=0;
    unsigned char inbuf[1024], outbuf[1024+EVP_MAX_BLOCK_LENGTH];
    const EVP_CIPHER *cipher=((cname)?(EVP_get_cipherbyname(cname)):
			      (EVP_aes_128_cbc()));

    if (cipher) {
      int needkeylen=EVP_CIPHER_key_length(cipher);
      int needivlen=EVP_CIPHER_iv_length(cipher);
      int blocksize=EVP_CIPHER_block_size(cipher);
      if (blocksize>1024) blocksize=1024;
      u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
	     " %s cipher=%s, keylen=%d/%d, ivlen=%d/%d, blocksize=%d\n",
	     ((do_encrypt)?("encrypt"):("decrypt")),
	     cname,keylen,needkeylen,ivlen,needivlen,blocksize);

      if ((needivlen)&&(ivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      memset(&ctx,0,sizeof(ctx));

      EVP_CIPHER_CTX_init(&ctx);

      retval=EVP_CipherInit(&ctx, cipher, NULL, NULL, do_encrypt);
      if (retval==0)
	return u8_reterr(u8_CipherInit_Failed,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_strdup(cname));

      retval=EVP_CIPHER_CTX_set_key_length(&ctx,keylen);
      if (retval==0)
	return u8_reterr(u8_BadCryptoKey,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",keylen,needkeylen,cname));

      if ((needivlen)&&(ivlen!=needivlen))
	return u8_reterr(u8_BadCryptoIV,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_mkstring("%d!=%d(%s)",ivlen,needivlen,cname));

      retval=EVP_CipherInit(&ctx, cipher, key, iv, do_encrypt);
      if (retval==0)
	return u8_reterr(u8_CipherInit_Failed,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 u8_strdup(cname));

      while (1) {
	inlen = reader(inbuf,blocksize,readstate);
	if (inlen <= 0) {
	  u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
		 "Finished %s(%s) with %ld in, %ld out",
		 ((do_encrypt)?("encrypt"):("decrypt")),
		 cname,totalin,totalout);
	  break;}
	else totalin=totalin+inlen;
	if (!(EVP_CipherUpdate(&ctx,outbuf,&outlen,inbuf,inlen))) {
	  char *details=u8_malloc(256);
	  unsigned long err=ERR_get_error();
	  ERR_error_string_n(err,details,256);
	  EVP_CIPHER_CTX_cleanup(&ctx);
	  return u8_reterr(u8_InternalCryptoError,
			   ((caller)?(caller):((u8_context)"u8_cryptic")),
			   details);}
	else {
	  u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
		 "%s(%s) consumed %d/%ld bytes, emitted %d/%ld bytes"
		 " in=<%v>\n out=<%v>",
		 ((do_encrypt)?("encrypt"):("decrypt")),cname,
		 inlen,totalin,outlen,totalout+outlen,
		 inbuf,inlen,outbuf,outlen);
	  writer(outbuf,outlen,writestate);
	  totalout=totalout+outlen;}}
      if (!(EVP_CipherFinal(&ctx,outbuf,&outlen))) {
	char *details=u8_malloc(256);
	unsigned long err=ERR_get_error();
	ERR_error_string_n(err,details,256);
	EVP_CIPHER_CTX_cleanup(&ctx);
	return u8_reterr(u8_InternalCryptoError,
			 ((caller)?(caller):(OPENSSL_CRYPTIC)),
			 details);}
      else {
	writer(outbuf,outlen,writestate);
	u8_log(CRYPTO_LOGLEVEL,OPENSSL_CRYPTIC,
	       "%s(%s) done after consuming %ld/%ld bytes, emitting %ld/%ld bytes"
	       "\n final out=<%v>",
	       ((do_encrypt)?("encrypt"):("decrypt")),cname,
	       inlen,totalin,outlen,totalout+outlen,
	       outbuf,outlen);
	EVP_CIPHER_CTX_cleanup(&ctx);
	totalout=totalout+outlen;
	return totalout;}}
    else {
      char *details=u8_malloc(256);
      unsigned long err=ERR_get_error();
      ERR_error_string_n(err,details,256);
      return u8_reterr("Unknown cipher",
		       ((caller)?(caller):((u8_context)"u8_cryptic")),
		       details);}
  }
}
示例#16
0
// Signing functions
bool OSSLGOST::sign(PrivateKey* privateKey, const ByteString& dataToSign,
		    ByteString& signature, const AsymMech::Type mechanism,
		    const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
	if (mechanism == AsymMech::GOST)
	{
		// Separate implementation for GOST signing without hash computation

		// Check if the private key is the right type
		if (!privateKey->isOfType(OSSLGOSTPrivateKey::type))
		{
			ERROR_MSG("Invalid key type supplied");

			return false;
		}

		// In case of raw GOST, the length of the input data must be 32 bytes
		if (dataToSign.size() != 32)
		{
			ERROR_MSG("Size of data to sign is not 32 bytes");

			return false;
		}

		// Perform the signature operation
		OSSLGOSTPrivateKey* osslKey = (OSSLGOSTPrivateKey*) privateKey;
		EVP_PKEY* pkey = osslKey->getOSSLKey();
		size_t outLen;

		if (pkey == NULL)
		{
			ERROR_MSG("Could not get the OpenSSL private key");

			return false;
		}

		signature.resize(EVP_PKEY_size(pkey));
		outLen = signature.size();

		EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL);
		if (ctx == NULL)
		{
			ERROR_MSG("EVP_PKEY_CTX_new failed");
			return false;
		}

		if (EVP_PKEY_sign_init(ctx) <= 0)
		{
			ERROR_MSG("EVP_PKEY_sign_init failed");
			EVP_PKEY_CTX_free(ctx);
			return false;
		}

		if (EVP_PKEY_sign(ctx, &signature[0], &outLen, dataToSign.const_byte_str(), dataToSign.size()) <= 0)
		{
			ERROR_MSG("An error occurred while performing a signature");
			EVP_PKEY_CTX_free(ctx);
			return false;
		}

		signature.resize(outLen);
		EVP_PKEY_CTX_free(ctx);

		return true;
	}
	else
	{
		// Call default implementation
		return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
	}
}
示例#17
0
BUF_MEM *
EAC_sign(int protocol, EVP_PKEY *key, const BUF_MEM *data)
{
    BUF_MEM *signature = NULL, *signature_data = NULL, *plain_sig = NULL;
    EVP_PKEY_CTX *tmp_key_ctx = NULL;
    size_t len;
    const EVP_MD *md = eac_oid2md(protocol);
    int type;

    check((key && data), "Invalid arguments");

    tmp_key_ctx = EVP_PKEY_CTX_new(key, NULL);
    if (!tmp_key_ctx || !md
               || EVP_PKEY_sign_init(tmp_key_ctx) <= 0
            || EVP_PKEY_CTX_set_signature_md(tmp_key_ctx, md) <= 0)
        goto err;


    type = EVP_PKEY_base_id(key);
    if (       protocol == NID_id_TA_ECDSA_SHA_1
            || protocol == NID_id_TA_ECDSA_SHA_224
            || protocol == NID_id_TA_ECDSA_SHA_256
            || protocol == NID_id_TA_ECDSA_SHA_384
            || protocol == NID_id_TA_ECDSA_SHA_512) {
        if (!(type == EVP_PKEY_EC))
            goto err;

    } else if (protocol == NID_id_TA_RSA_v1_5_SHA_1
            || protocol == NID_id_TA_RSA_v1_5_SHA_256
            || protocol == NID_id_TA_RSA_v1_5_SHA_512) {
        if (!(type == EVP_PKEY_RSA))
            goto err;

        if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PADDING))
            goto err;

    } else if (protocol == NID_id_TA_RSA_PSS_SHA_1
            || protocol == NID_id_TA_RSA_PSS_SHA_256
            || protocol == NID_id_TA_RSA_PSS_SHA_512) {
        if (!(type == EVP_PKEY_RSA))
            goto err;

        if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PSS_PADDING))
            goto err;

    } else {
        goto err;
    }

    /* EVP_PKEY_sign doesn't perform hashing (despite EVP_PKEY_CTX_set_signature_md).
     * Therefore we need to compute the hash ourself. */
    signature_data = hash(md, NULL, NULL, data);
    if (!signature_data)
        goto err;


    /* Actual signature creation */
    if (EVP_PKEY_sign(tmp_key_ctx, NULL, &len,
               (unsigned char*) signature_data->data,
               signature_data->length) <= 0)
        goto err;
    signature = BUF_MEM_create(len);
    if (!signature)
        goto err;
    if (EVP_PKEY_sign(tmp_key_ctx,
                (unsigned char *) signature->data,
                &signature->length,
                (unsigned char*) signature_data->data,
                signature_data->length) <= 0)
        goto err;


    /* EAC signatures are always in plain signature format for EC curves but
     * OpenSSL only creates X.509 format. Therefore we need to convert between
     * these formats. */
    if (       protocol == NID_id_TA_ECDSA_SHA_1
            || protocol == NID_id_TA_ECDSA_SHA_224
            || protocol == NID_id_TA_ECDSA_SHA_256
            || protocol == NID_id_TA_ECDSA_SHA_384
            || protocol == NID_id_TA_ECDSA_SHA_512) {
        plain_sig = convert_to_plain_sig(signature);
        BUF_MEM_free(signature);
        signature = plain_sig;
    }

err:
    if (tmp_key_ctx)
        EVP_PKEY_CTX_free(tmp_key_ctx);
    if (signature_data)
        BUF_MEM_free(signature_data);

    return signature;
}
示例#18
0
int main(int argc, char **argv)
{
	EVP_PKEY *private_key, *public_key;
	EVP_PKEY_CTX *pkey_ctx;
	EVP_MD_CTX *md_ctx;

	const EVP_MD *digest_algo;

	char *private_key_name, *public_key_name;

	unsigned char sig[4096];
	size_t sig_len;

	unsigned char md[128];
	size_t md_len;
	unsigned digest_len;

	char *key_pass = NULL;
	const char *module_path, *efile;

	ENGINE *e;

	int ret;

	if (argc < 5) {
		fprintf(stderr, "usage: %s [PIN] [CONF] [private key URL] [public key URL] [module]\n", argv[0]);
		fprintf(stderr, "\n");
		exit(1);
	}

	key_pass = argv[1];
	efile = argv[2];
	private_key_name = argv[3];
	public_key_name = argv[4];
	module_path = argv[5];

	ret = CONF_modules_load_file(efile, "engines", 0);
	if (ret <= 0) {
		fprintf(stderr, "cannot load %s\n", efile);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	ENGINE_add_conf_module();
#if OPENSSL_VERSION_NUMBER>=0x10100000
	OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
		| OPENSSL_INIT_ADD_ALL_DIGESTS \
		| OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
	OpenSSL_add_all_algorithms();
	OpenSSL_add_all_digests();
	ERR_load_crypto_strings();
#endif
	ERR_clear_error();

	ENGINE_load_builtin_engines();
	e = ENGINE_by_id("pkcs11");
	if (e == NULL) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", module_path, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_init(e)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (key_pass && !ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL);
	if (private_key == NULL) {
		fprintf(stderr, "cannot load: %s\n", private_key_name);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	public_key = ENGINE_load_public_key(e, public_key_name, NULL, NULL);
	if (public_key == NULL) {
		fprintf(stderr, "cannot load: %s\n", public_key_name);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	digest_algo = EVP_get_digestbyname("sha256");

#define TEST_DATA "test data"

	md_ctx = EVP_MD_CTX_create();
	if (EVP_DigestInit(md_ctx, digest_algo) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_DigestUpdate(md_ctx, TEST_DATA, sizeof(TEST_DATA)) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	digest_len = sizeof(md);
	if (EVP_DigestFinal(md_ctx, md, &digest_len) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}
	md_len = digest_len;

	EVP_MD_CTX_destroy(md_ctx);

	/* Sign the hash */
	pkey_ctx = EVP_PKEY_CTX_new(private_key, e);

	if (pkey_ctx == NULL) {
		fprintf(stderr, "Could not create context\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_sign_init(pkey_ctx) <= 0) {
		fprintf(stderr, "Could not init signature\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
		fprintf(stderr, "Could not set padding\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) {
		fprintf(stderr, "Could not set message digest algorithm\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	sig_len = sizeof(sig);
	if (EVP_PKEY_sign(pkey_ctx, sig, &sig_len, md,
			EVP_MD_size(digest_algo)) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	EVP_PKEY_CTX_free(pkey_ctx);

	printf("Signature created\n");

#if OPENSSL_VERSION_NUMBER >= 0x1000000fL

	pkey_ctx = EVP_PKEY_CTX_new(public_key, e);

	if (pkey_ctx == NULL) {
		fprintf(stderr, "Could not create context\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_verify_init(pkey_ctx) <= 0) {
		fprintf(stderr, "Could not init verify\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
		fprintf(stderr, "Could not set padding\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) {
		fprintf(stderr, "Could not set message digest algorithm\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	ret = EVP_PKEY_verify(pkey_ctx, sig, sig_len, md, md_len);
	if (ret < 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	EVP_PKEY_CTX_free(pkey_ctx);

	if (ret == 1) {
		printf("Signature verified\n");
	}
	else {
		printf("Verification failed\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

#else /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */

	printf("Unable to verify signature with %s\n", OPENSSL_VERSION_TEXT);

#endif /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */

	ENGINE_finish(e);
	CONF_modules_unload(1);
	return 0;
}