static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, int is_verify) { if (ctx->pctx == NULL) { ctx->pctx = EVP_PKEY_CTX_new(pkey, e); } if (ctx->pctx == NULL) { return 0; } ctx->pctx_ops = &md_pctx_ops; if (type == NULL) { type = EVP_sha1(); } if (type == NULL) { OPENSSL_PUT_ERROR(EVP, do_sigver_init, EVP_R_NO_DEFAULT_DIGEST); return 0; } if (is_verify) { if (ctx->pctx->pmeth->verifyctx_init) { if (!ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx)) { return 0; } ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; } else if (!EVP_PKEY_verify_init(ctx->pctx)) { return 0; } } else { if (ctx->pctx->pmeth->signctx_init) { if (!ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx)) { return 0; } ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; } else if (!EVP_PKEY_sign_init(ctx->pctx)) { return 0; } } if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) { return 0; } if (pctx) { *pctx = ctx->pctx; } if (!EVP_DigestInit_ex(ctx, type, e)) { return 0; } return 1; }
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, int ver) { if (ctx->pctx == NULL) ctx->pctx = EVP_PKEY_CTX_new(pkey, e); if (ctx->pctx == NULL) return 0; if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) { if (type == NULL) { int def_nid; if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) type = EVP_get_digestbynid(def_nid); } if (type == NULL) { EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); return 0; } } if (ver) { if (ctx->pctx->pmeth->verifyctx_init) { if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0) return 0; ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) return 0; } else { if (ctx->pctx->pmeth->signctx_init) { if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0) { return 0; } ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) return 0; } if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) return 0; if (pctx) *pctx = ctx->pctx; if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) return 1; if (!EVP_DigestInit_ex(ctx, type, e)) return 0; return 1; }
int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len = 0; int i = 0; EVP_PKEY_CTX *pkctx = NULL; 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_VERIFYFINAL, 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; } i = -1; pkctx = EVP_PKEY_CTX_new(pkey, NULL); if (pkctx == NULL) goto err; if (EVP_PKEY_verify_init(pkctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0) goto err; i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); err: EVP_PKEY_CTX_free(pkctx); return i; }
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, int is_verify) { if (ctx->pctx == NULL) { ctx->pctx = EVP_PKEY_CTX_new(pkey, e); } if (ctx->pctx == NULL) { return 0; } ctx->pctx_ops = &md_pctx_ops; if (type == NULL) { OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST); return 0; } if (is_verify) { if (!EVP_PKEY_verify_init(ctx->pctx)) { return 0; } } else { if (!EVP_PKEY_sign_init(ctx->pctx)) { return 0; } } if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) { return 0; } if (pctx) { *pctx = ctx->pctx; } if (!EVP_DigestInit_ex(ctx, type, e)) { return 0; } return 1; }
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, const int engine_impl, EVP_PKEY **ppkey) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; ENGINE *impl = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(keyfile, keyform, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; case KEY_NONE: break; } #ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; #endif if (kdfalg != NULL) { int kdfnid = OBJ_sn2nid(kdfalg); if (kdfnid == NID_undef) { kdfnid = OBJ_ln2nid(kdfalg); if (kdfnid == NID_undef) { BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", kdfalg); goto end; } } ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); } else { EC_KEY *eckey = NULL; const EC_GROUP *group = NULL; int nid; if (pkey == NULL) goto end; /* SM2 needs a special treatment */ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (nid = EC_GROUP_get_curve_name(group)) == 0) goto end; if (nid == NID_sm2) EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); } *pkeysize = EVP_PKEY_size(pkey); ctx = EVP_PKEY_CTX_new(pkey, impl); if (ppkey != NULL) *ppkey = pkey; EVP_PKEY_free(pkey); } if (ctx == NULL) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: OPENSSL_free(passin); return ctx; }
int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey) { unsigned char m[EVP_MAX_MD_SIZE]; unsigned int m_len; int i = 0,ok = 0,v; EVP_PKEY_CTX *pkctx = NULL; if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { if (!EVP_DigestFinal_ex(ctx, m, &m_len)) goto err; } else { int rv; EVP_MD_CTX tmp_ctx; EVP_MD_CTX_init(&tmp_ctx); rv = EVP_MD_CTX_copy_ex(&tmp_ctx,ctx); if (rv) rv = EVP_DigestFinal_ex(&tmp_ctx, m, &m_len); EVP_MD_CTX_cleanup(&tmp_ctx); if (!rv) return 0; } if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) { i = -1; pkctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkctx) goto err; if (EVP_PKEY_verify_init(pkctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0) goto err; i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); 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_VERIFYFINAL,EVP_R_WRONG_PUBLIC_KEY_TYPE); return(-1); } if (ctx->digest->verify == NULL) { EVPerr(EVP_F_EVP_VERIFYFINAL,EVP_R_NO_VERIFY_FUNCTION_CONFIGURED); return(0); } return(ctx->digest->verify(ctx->digest->type,m,m_len, sigbuf,siglen,pkey->pkey.ptr)); }
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 CK_RV gostr3410_verify_data(const unsigned char *pubkey, int pubkey_len, const unsigned char *params, int params_len, unsigned char *data, int data_len, unsigned char *signat, int signat_len) { EVP_PKEY *pkey; EVP_PKEY_CTX *pkey_ctx; EC_POINT *P; BIGNUM *X, *Y; ASN1_OCTET_STRING *octet; const EC_GROUP *group = NULL; char paramset[2] = "A"; int r = -1, ret_vrf = 0; pkey = EVP_PKEY_new(); if (!pkey) return CKR_HOST_MEMORY; r = EVP_PKEY_set_type(pkey, NID_id_GostR3410_2001); if (r == 1) { pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkey_ctx) { EVP_PKEY_free(pkey); return CKR_HOST_MEMORY; } /* FIXME: fully check params[] */ if (params_len > 0 && params[params_len - 1] >= 1 && params[params_len - 1] <= 3) { paramset[0] += params[params_len - 1] - 1; r = EVP_PKEY_CTX_ctrl_str(pkey_ctx, "paramset", paramset); } else r = -1; if (r == 1) r = EVP_PKEY_paramgen_init(pkey_ctx); if (r == 1) r = EVP_PKEY_paramgen(pkey_ctx, &pkey); if (r == 1 && EVP_PKEY_get0(pkey) != NULL) group = EC_KEY_get0_group(EVP_PKEY_get0(pkey)); r = -1; if (group) octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey, (long)pubkey_len); if (group && octet) { reverse(octet->data, octet->length); Y = BN_bin2bn(octet->data, octet->length / 2, NULL); X = BN_bin2bn((const unsigned char*)octet->data + octet->length / 2, octet->length / 2, NULL); ASN1_OCTET_STRING_free(octet); P = EC_POINT_new(group); if (P && X && Y) r = EC_POINT_set_affine_coordinates_GFp(group, P, X, Y, NULL); BN_free(X); BN_free(Y); if (r == 1 && EVP_PKEY_get0(pkey) && P) r = EC_KEY_set_public_key(EVP_PKEY_get0(pkey), P); EC_POINT_free(P); } if (r == 1) { r = EVP_PKEY_verify_init(pkey_ctx); reverse(data, data_len); if (r == 1) ret_vrf = EVP_PKEY_verify(pkey_ctx, signat, signat_len, data, data_len); } } EVP_PKEY_CTX_free(pkey_ctx); EVP_PKEY_free(pkey); if (r != 1) return CKR_GENERAL_ERROR; return ret_vrf == 1 ? CKR_OK : CKR_SIGNATURE_INVALID; }
/* * verify EC signature on JWT */ static apr_byte_t apr_jws_verify_ec(apr_pool_t *pool, apr_jwt_t *jwt, apr_jwk_t *jwk, apr_jwt_error_t *err) { int nid = apr_jws_ec_alg_to_curve(jwt->header.alg); if (nid == -1) { apr_jwt_error(err, "no OpenSSL Elliptic Curve identifier found for algorithm \"%s\"", jwt->header.alg); return FALSE; } EC_GROUP *curve = EC_GROUP_new_by_curve_name(nid); if (curve == NULL) { apr_jwt_error(err, "no OpenSSL Elliptic Curve found for algorithm \"%s\"", jwt->header.alg); return FALSE; } apr_byte_t rc = FALSE; /* get the OpenSSL digest function */ const EVP_MD *digest = NULL; if ((digest = apr_jws_crypto_alg_to_evp(pool, jwt->header.alg, err)) == NULL) return FALSE; EVP_MD_CTX ctx; EVP_MD_CTX_init(&ctx); EC_KEY * pubkey = EC_KEY_new(); EC_KEY_set_group(pubkey, curve); BIGNUM * x = BN_new(); BIGNUM * y = BN_new(); BN_bin2bn(jwk->key.ec->x, jwk->key.ec->x_len, x); BN_bin2bn(jwk->key.ec->y, jwk->key.ec->y_len, y); if (!EC_KEY_set_public_key_affine_coordinates(pubkey, x, y)) { apr_jwt_error_openssl(err, "EC_KEY_set_public_key_affine_coordinates"); return FALSE; } EVP_PKEY* pEcKey = EVP_PKEY_new(); if (!EVP_PKEY_assign_EC_KEY(pEcKey, pubkey)) { pEcKey = NULL; apr_jwt_error_openssl(err, "EVP_PKEY_assign_EC_KEY"); goto end; } ctx.pctx = EVP_PKEY_CTX_new(pEcKey, NULL); if (!EVP_PKEY_verify_init(ctx.pctx)) { apr_jwt_error_openssl(err, "EVP_PKEY_verify_init"); goto end; } if (!EVP_VerifyInit_ex(&ctx, digest, NULL)) { apr_jwt_error_openssl(err, "EVP_VerifyInit_ex"); goto end; } if (!EVP_VerifyUpdate(&ctx, jwt->message, strlen(jwt->message))) { apr_jwt_error_openssl(err, "EVP_VerifyUpdate"); goto end; } if (!EVP_VerifyFinal(&ctx, (const unsigned char *) jwt->signature.bytes, jwt->signature.length, pEcKey)) { apr_jwt_error_openssl(err, "wrong key? EVP_VerifyFinal"); goto end; } rc = TRUE; end: if (pEcKey) { EVP_PKEY_free(pEcKey); } else if (pubkey) { EC_KEY_free(pubkey); } EVP_MD_CTX_cleanup(&ctx); return rc; }
static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo) { int rc, ret; EVP_PKEY_CTX *pkey_ctx = NULL; struct pgpDigSigRSA_s *sig = pgpsig->data; void *padded_sig = NULL; struct pgpDigKeyRSA_s *key = pgpkey->data; if (!constructRSASigningKey(key)) { rc = 1; goto done; } pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL); if (!pkey_ctx) { rc = 1; goto done; } ret = EVP_PKEY_verify_init(pkey_ctx); if (ret < 0) { rc = 1; goto done; } ret = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PADDING); if (ret < 0) { rc = 1; goto done; } ret = EVP_PKEY_CTX_set_signature_md(pkey_ctx, getEVPMD(hash_algo)); if (ret < 0) { rc = 1; goto done; } int pkey_len = EVP_PKEY_size(key->evp_pkey); padded_sig = xcalloc(1, pkey_len); if (!BN_bn2binpad(sig->bn, padded_sig, pkey_len)) { rc = 1; goto done; } ret = EVP_PKEY_verify(pkey_ctx, padded_sig, pkey_len, hash, hashlen); if (ret == 1) { /* Success */ rc = 0; } else { /* Failure */ rc = 1; } done: EVP_PKEY_CTX_free(pkey_ctx); free(padded_sig); return rc; }
int EAC_verify(int protocol, EVP_PKEY *key, const BUF_MEM *signature, const BUF_MEM *data) { BUF_MEM *verification_data = NULL, *signature_to_verify = NULL; EVP_PKEY_CTX *tmp_key_ctx = NULL; int ret = -1; const EVP_MD *md = eac_oid2md(protocol); int type; check((key && signature), "Invalid arguments"); tmp_key_ctx = EVP_PKEY_CTX_new(key, NULL); if (!tmp_key_ctx || !md || EVP_PKEY_verify_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; /* 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. */ signature_to_verify = convert_from_plain_sig(signature); if (!signature_to_verify) 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; signature_to_verify = BUF_MEM_create_init(signature->data, signature->length); if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PADDING) || !signature_to_verify) 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; signature_to_verify = BUF_MEM_create_init(signature->data, signature->length); if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PSS_PADDING) || !signature_to_verify) 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. */ verification_data = hash(md, NULL, NULL, data); if (!verification_data) goto err; /* Actual signature verification */ ret = EVP_PKEY_verify(tmp_key_ctx, (unsigned char*) signature_to_verify->data, signature_to_verify->length, (unsigned char*) verification_data->data, verification_data->length); err: if (verification_data) BUF_MEM_free(verification_data); if (signature_to_verify) BUF_MEM_free(signature_to_verify); if (tmp_key_ctx) EVP_PKEY_CTX_free(tmp_key_ctx); return ret; }
static EVP_PKEY_CTX * init_ctx(int *pkeysize, char *keyfile, int keyform, int key_type, char *passargin, int pkey_op) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(bio_err, keyfile, keyform, 0, passin, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL, "Public Key"); break; case KEY_CERT: x = load_cert(bio_err, keyfile, keyform, NULL, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; } *pkeysize = EVP_PKEY_size(pkey); if (!pkey) goto end; ctx = EVP_PKEY_CTX_new(pkey, NULL); EVP_PKEY_free(pkey); if (!ctx) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: free(passin); return ctx; }
bool bdoc::X509Cert::verifySignature(int digestMethod, int digestSize, std::vector<unsigned char> digest, std::vector<unsigned char> signature) { int result = 0; EVP_PKEY* key = getPublicKey(); switch (EVP_PKEY_type(key->type)) { case EVP_PKEY_RSA: { if (digest.size() > static_cast<size_t>(digestSize)) { // The digest already has an ASN.1 DigestInfo header. break; } X509_SIG *sig = X509_SIG_new(); // Prefer set0 to set_md, so we don't have to initialize the // digest lookup table with OpenSSL_add_all_digests. None of // our supported digests have parameters anyway. X509_ALGOR_set0(sig->algor, OBJ_nid2obj(digestMethod), V_ASN1_NULL, NULL); ASN1_OCTET_STRING_set(sig->digest, &digest[0], digest.size()); unsigned char *asn1 = NULL; size_t asn1_len = i2d_X509_SIG(sig, &asn1); digest = std::vector<unsigned char>(asn1, asn1 + asn1_len); X509_SIG_free(sig); break; } case EVP_PKEY_EC: { ECDSA_SIG *sig = ECDSA_SIG_new(); // signature is just r and s concatenated, so split them. size_t n_len = signature.size() >> 1; BN_bin2bn(&signature[0], n_len, sig->r); BN_bin2bn(&signature[n_len], n_len, sig->s); unsigned char *asn1 = NULL; size_t asn1_len = i2d_ECDSA_SIG(sig, &asn1); signature = std::vector<unsigned char>(asn1, asn1 + asn1_len); ECDSA_SIG_free(sig); break; } default: THROW_STACK_EXCEPTION("Certificate '%s' has an unsupported " "public key type, can not verify signature.", getSubject().c_str()); } EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); if (!ctx) { EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Creating signature verification " "context failed: %s", ERR_reason_error_string(ERR_get_error())); } if (EVP_PKEY_verify_init(ctx) <= 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Initializing signature " "verification context failed: %s", ERR_reason_error_string(ERR_get_error())); } result = EVP_PKEY_verify(ctx, &signature[0], signature.size(), &digest[0], digest.size()); if (result < 0) { EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); THROW_STACK_EXCEPTION("Error during signature verification: %s", ERR_reason_error_string(ERR_get_error())); } EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(key); return (result == 1); }
DWORD VmDirVerifyRSASignature( EVP_PKEY* pPubKey, const EVP_MD* digestMethod, const unsigned char* pData, size_t dataSize, const unsigned char* pSignature, size_t signatureSize, PBOOLEAN pVerified ) { DWORD dwError = 0; int retVal = 0; unsigned char* pMd = NULL; size_t mdSize = 0; EVP_PKEY_CTX* pPubKeyCtx = NULL; if (!pPubKey || !digestMethod || !pData || !pData || !pVerified) { BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_INVALID_PARAMETER); } dwError = VmDirComputeMessageDigest(digestMethod, pData, dataSize, &pMd, &mdSize); BAIL_ON_VMDIR_ERROR(dwError); pPubKeyCtx = EVP_PKEY_CTX_new(pPubKey, NULL); if (!pPubKeyCtx) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_new returned NULL", __FUNCTION__); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_verify_init(pPubKeyCtx); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_verify_init returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_CTX_set_rsa_padding(pPubKeyCtx, RSA_PKCS1_PADDING); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_set_rsa_padding returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_CTX_set_signature_md(pPubKeyCtx, digestMethod); if (retVal <= 0) { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_CTX_set_signature_md returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } retVal = EVP_PKEY_verify(pPubKeyCtx, pSignature, signatureSize, pMd, mdSize); if (retVal == 1) { *pVerified = TRUE; } else if (retVal == 0) { *pVerified = FALSE; } else { VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s: EVP_PKEY_verify returned %d", __FUNCTION__, retVal); BAIL_WITH_VMDIR_ERROR(dwError, VMDIR_ERROR_SSL); } cleanup: VMDIR_SAFE_FREE_MEMORY(pMd); EVP_PKEY_CTX_free(pPubKeyCtx); return dwError; error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "%s failed with error (%d)", __FUNCTION__, dwError); goto cleanup; }
int verify(const char* keypath, BIGNUM* nonce, const uint8_t* sig, size_t slen){ // Nonce uint8_t* N; size_t Nlen; // Context and key EVP_PKEY_CTX *verctx; FILE* vkeyfh; EVP_PKEY *vkey=NULL; // Return codes and errors int err_code, ret_val=1; unsigned long vererr; /* * Open the public key of the client for verification */ vkeyfh = fopen(keypath,"r"); if(!vkeyfh) { fprintf(stderr, "%s: Cannot open the key file\n", __func__); ret_val = 0; goto exit_verify; } vkey = PEM_read_PUBKEY(vkeyfh, &vkey, NULL, NULL); if(!vkey){ fprintf(stderr,"Cannot read verification key from file %s\n", keypath); ret_val = 0; fclose(vkeyfh); goto exit_verify; } verctx = EVP_PKEY_CTX_new(vkey, NULL); if (!verctx){ fprintf(stderr,"Cannot create a verify context\n"); ret_val = 0; fclose(vkeyfh); EVP_PKEY_free(vkey); goto exit_verify; } if (EVP_PKEY_verify_init(verctx) <= 0){ fprintf(stderr,"Cannot initialize a verify context\n"); ret_val = 0; goto cleanup_verify; } /* * Convert the nonce in a string so that it can be verified */ N = malloc(BN_num_bytes(nonce)); if (N == NULL) { fprintf(stderr, "%s: Out of memory\n", __func__); ret_val = 0; goto cleanup_verify; } Nlen = BN_bn2bin(nonce, N); /* Perform actual verify operation */ err_code = EVP_PKEY_verify(verctx, sig, slen, N, Nlen); if( err_code != 1 ){ ERR_load_crypto_strings(); vererr = ERR_get_error(); fprintf(stderr,"The verify operation on the nonce has failed with code %lu. RET=%d\n",vererr,err_code); fprintf(stderr,"%s\n", ERR_error_string(vererr, NULL)); ERR_free_strings(); ret_val = 0; } free(N); cleanup_verify: EVP_PKEY_CTX_free(verctx); EVP_PKEY_free(vkey); fclose(vkeyfh); exit_verify: return ret_val; }
static VALUE ORPV__verify_pss_sha1(VALUE self, VALUE vPubKey, VALUE vSig, VALUE vHashData, VALUE vSaltLen) { enum ORPV_errors err = OK; BIO * pkey_bio = NULL; RSA * rsa_pub_key = NULL; EVP_PKEY * pkey = NULL; EVP_PKEY_CTX * pkey_ctx = NULL; char * pub_key = NULL; int verify_rval = -1, salt_len; char ossl_err_strs[(OSSL_ERR_STR_LEN + 2) * ORPV_MAX_ERRS] = ""; if (ERR_peek_error()) { err = EXTERNAL; goto Cleanup; } vPubKey = StringValue(vPubKey); vSig = StringValue(vSig); vHashData = StringValue(vHashData); salt_len = NUM2INT(vSaltLen); if (RSTRING_LEN(vPubKey) > (long)INT_MAX) { err = KEY_OVERFLOW; goto Cleanup; } pub_key = malloc(RSTRING_LEN(vPubKey)); if (! pub_key) { err = NOMEM; goto Cleanup; } memcpy(pub_key, StringValuePtr(vPubKey), RSTRING_LEN(vPubKey)); pkey_bio = BIO_new_mem_buf(pub_key, (int)RSTRING_LEN(vPubKey)); rsa_pub_key = PEM_read_bio_RSA_PUBKEY(pkey_bio, NULL, NULL, NULL); if (! rsa_pub_key) { err = PUBKEY_PARSE; goto Cleanup; } pkey = EVP_PKEY_new(); if (! pkey) { err = PKEY_INIT; goto Cleanup; } if (! EVP_PKEY_set1_RSA(pkey, rsa_pub_key)) { err = RSA_ASSIGN; goto Cleanup; } pkey_ctx = EVP_PKEY_CTX_new(pkey, ENGINE_get_default_RSA()); if (! pkey_ctx) { err = PKEY_CTX_INIT; goto Cleanup; } if (EVP_PKEY_verify_init(pkey_ctx) <= 0) { err = VERIFY_INIT; goto Cleanup; } if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, EVP_sha1()) <= 0) { err = SET_SIG_MD; goto Cleanup; } if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) { err = SET_PADDING; goto Cleanup; } if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) <= 0) { err = SET_SALTLEN; goto Cleanup; } verify_rval = EVP_PKEY_verify(pkey_ctx, (unsigned char*)StringValuePtr(vSig), (size_t)RSTRING_LEN(vSig), (unsigned char*)StringValuePtr(vHashData), (size_t)RSTRING_LEN(vHashData)); Cleanup: /* * BIO * pkey_bio = NULL; * RSA * rsa_pub_key = NULL; * EVP_PKEY * pkey = NULL; * EVP_PKEY_CTX * pkey_ctx = NULL; * char * pub_key = NULL; */ if (pkey_ctx) EVP_PKEY_CTX_free(pkey_ctx); if (pkey) EVP_PKEY_free(pkey); if (rsa_pub_key) RSA_free(rsa_pub_key); if (pkey_bio) BIO_free(pkey_bio); if (pub_key) free(pub_key); switch (err) { case OK: switch (verify_rval) { case 1: return Qtrue; case 0: return Qfalse; default: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "An error occurred during validation.\n%s", ossl_err_strs); } break; case EXTERNAL: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_eRuntimeError, "OpenSSL was in an error state prior to invoking this verification.\n%s", ossl_err_strs); break; case KEY_OVERFLOW: rb_raise(rb_cRSAError, "Your public key is too big. How is that even possible?"); break; case NOMEM: rb_raise(rb_const_get_at(rb_mErrno, rb_intern("ENOMEM")), "Insufficient memory to allocate pubkey copy. Woof."); break; case PUBKEY_PARSE: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Error parsing public key\n%s", ossl_err_strs); break; case PKEY_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize PKEY\n%s", ossl_err_strs); break; case RSA_ASSIGN: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to assign RSA object to PKEY\n%s", ossl_err_strs); break; case PKEY_CTX_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize PKEY context.\n%s", ossl_err_strs); break; case VERIFY_INIT: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to initialize verification process.\n%s", ossl_err_strs); break; case SET_SIG_MD: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set signature message digest to SHA1.\n%s", ossl_err_strs); break; case SET_PADDING: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set PSS padding.\n%s", ossl_err_strs); break; case SET_SALTLEN: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_cRSAError, "Failed to set salt length.\n%s", ossl_err_strs); break; default: bind_err_strs(ossl_err_strs, ORPV_MAX_ERRS); rb_raise(rb_eRuntimeError, "Something has gone horribly wrong.\n%s", ossl_err_strs); } return Qnil; }
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; }
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; }
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, const int engine_impl) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; ENGINE *impl = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(keyfile, keyform, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; case KEY_NONE: break; } #ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; #endif if (kdfalg) { int kdfnid = OBJ_sn2nid(kdfalg); if (kdfnid == NID_undef) goto end; ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); } else { if (pkey == NULL) goto end; *pkeysize = EVP_PKEY_size(pkey); ctx = EVP_PKEY_CTX_new(pkey, impl); EVP_PKEY_free(pkey); } if (ctx == NULL) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: OPENSSL_free(passin); return ctx; }