/** * ECDSA signing method (replaces ossl_ecdsa_sign_sig) * * @param dgst hash value to sign * @param dlen length of the hash value * @param kinv precomputed inverse k (from the sign_setup method) * @param rp precomputed rp (from the sign_setup method) * @param ec private EC signing key * @return pointer to a ECDSA_SIG structure or NULL if an error occurred */ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *ec) { unsigned char sigret[512]; /* HACK for now */ ECDSA_SIG *sig; PKCS11_KEY *key; unsigned int siglen; BIGNUM *r, *s, *order; (void)kinv; /* Precomputed values are not used for PKCS#11 */ (void)rp; /* Precomputed values are not used for PKCS#11 */ key = pkcs11_get_ex_data_ec(ec); if (check_key_fork(key) < 0) { sign_sig_fn orig_sign_sig; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const EC_KEY_METHOD *meth = EC_KEY_OpenSSL(); EC_KEY_METHOD_get_sign((EC_KEY_METHOD *)meth, NULL, NULL, &orig_sign_sig); #else const ECDSA_METHOD *meth = ECDSA_OpenSSL(); orig_sign_sig = meth->ecdsa_do_sign; #endif return orig_sign_sig(dgst, dlen, kinv, rp, ec); } /* Truncate digest if its byte size is longer than needed */ order = BN_new(); if (order) { const EC_GROUP *group = EC_KEY_get0_group(ec); if (group && EC_GROUP_get_order(group, order, NULL)) { int klen = BN_num_bits(order); if (klen < 8*dlen) dlen = (klen+7)/8; } BN_free(order); } siglen = sizeof sigret; if (pkcs11_ecdsa_sign(dgst, dlen, sigret, &siglen, key) <= 0) return NULL; r = BN_bin2bn(sigret, siglen/2, NULL); s = BN_bin2bn(sigret + siglen/2, siglen/2, NULL); sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ECDSA_SIG_set0(sig, r, s); #else BN_free(sig->r); sig->r = r; BN_free(sig->s); sig->s = s; #endif return sig; }
int _libssh2_ecdsa_verify(libssh2_ecdsa_ctx * ctx, const unsigned char *r, size_t r_len, const unsigned char *s, size_t s_len, const unsigned char *m, size_t m_len) { int ret = 0; EC_KEY *ec_key = (EC_KEY*)ctx; libssh2_curve_type type = _libssh2_ecdsa_key_get_curve_type(ec_key); #ifdef HAVE_OPAQUE_STRUCTS ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); BIGNUM *pr = BN_new(); BIGNUM *ps = BN_new(); BN_bin2bn(r, r_len, pr); BN_bin2bn(s, s_len, ps); ECDSA_SIG_set0(ecdsa_sig, pr, ps); #else ECDSA_SIG ecdsa_sig_; ECDSA_SIG *ecdsa_sig = &ecdsa_sig_; ecdsa_sig_.r = BN_new(); BN_bin2bn(r, r_len, ecdsa_sig_.r); ecdsa_sig_.s = BN_new(); BN_bin2bn(s, s_len, ecdsa_sig_.s); #endif if(type == LIBSSH2_EC_CURVE_NISTP256) { LIBSSH2_ECDSA_VERIFY(256); } else if(type == LIBSSH2_EC_CURVE_NISTP384) { LIBSSH2_ECDSA_VERIFY(384); } else if(type == LIBSSH2_EC_CURVE_NISTP521) { LIBSSH2_ECDSA_VERIFY(512); } #ifdef HAVE_OPAQUE_STRUCTS if(ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); #else BN_clear_free(ecdsa_sig_.s); BN_clear_free(ecdsa_sig_.r); #endif return (ret == 1) ? 0 : -1; }
BUF_MEM * convert_from_plain_sig(const BUF_MEM *plain_sig) { ECDSA_SIG *ecdsa_sig = NULL; BIGNUM *r, *s; BUF_MEM *x962_sig = NULL; int l; unsigned char *p = NULL; check(plain_sig, "Invalid arguments"); check(plain_sig->length%2 == 0, "Invalid data"); ecdsa_sig = ECDSA_SIG_new(); if (!ecdsa_sig) goto err; /* The first l/2 bytes of the plain signature contain the number r, the second * l/2 bytes contain the number s. */ r = BN_bin2bn((unsigned char *) plain_sig->data, plain_sig->length/2, NULL); s = BN_bin2bn((unsigned char *) plain_sig->data + plain_sig->length/2, plain_sig->length/2, NULL); if (!r || !s || !ECDSA_SIG_set0(ecdsa_sig, r, s)) goto err; r = NULL; s = NULL; /* ASN.1 encode the signature*/ l = i2d_ECDSA_SIG(ecdsa_sig, &p); if (l < 0) goto err; x962_sig = BUF_MEM_create_init(p, l); err: if (p) OPENSSL_free(p); if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); if (r) BN_free(r); if (s) BN_free(s); return x962_sig; }
static bool _cjose_jws_verify_sig_ec(cjose_jws_t *jws, const cjose_jwk_t *jwk, cjose_err *err) { bool retval = false; // ensure jwk is EC if (jwk->kty != CJOSE_JWK_KTY_EC) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); return false; } ec_keydata *keydata = (ec_keydata *)jwk->keydata; EC_KEY *ec = keydata->key; ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); int key_len = jws->sig_len / 2; #if defined(CJOSE_OPENSSL_11X) BIGNUM *pr = BN_new(), *ps = BN_new(); BN_bin2bn(jws->sig, key_len, pr); BN_bin2bn(jws->sig + key_len, key_len, ps); ECDSA_SIG_set0(ecdsa_sig, pr, ps); #else BN_bin2bn(jws->sig, key_len, ecdsa_sig->r); BN_bin2bn(jws->sig + key_len, key_len, ecdsa_sig->s); #endif if (ECDSA_do_verify(jws->dig, jws->dig_len, ecdsa_sig, ec) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jws_verify_sig_ec_cleanup; } // if we got this far - success retval = true; _cjose_jws_verify_sig_ec_cleanup: if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); return retval; }
bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec) { if (rec<0 || rec>=3) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); // OpenSSL-1.1 compatibility layer: #if OPENSSL_VERSION_NUMBER > 0x1000ffffL BIGNUM *sig_r=BN_new(); BIGNUM *sig_s=BN_new(); BN_bin2bn(&p64[0], 32, sig_r); BN_bin2bn(&p64[32], 32, sig_s); ECDSA_SIG_set0(sig, sig_r, sig_s); #else BN_bin2bn(&p64[0], 32, sig->r); BN_bin2bn(&p64[32], 32, sig->s); #endif // bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1; ECDSA_SIG_free(sig); return ret; }
// reconstruct public key from a compact signature // This is only slightly more CPU intensive than just verifying it. // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool CKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.size() != 65) return false; int nV = vchSig[0]; if (nV<27 || nV>=35) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); if (!sig) return false; #if OPENSSL_VERSION_NUMBER > 0x1000ffffL // sig_r and sig_s are deallocated by ECDSA_SIG_free(sig); BIGNUM *sig_r = BN_bin2bn(&vchSig[1],32,BN_new()); BIGNUM *sig_s = BN_bin2bn(&vchSig[33],32,BN_new()); if (!sig_r || !sig_s) return false; // copy and transfer ownership to sig ECDSA_SIG_set0(sig, sig_r, sig_s); #else BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); #endif EC_KEY_free(pkey); pkey = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { SetCompressedPubKey(); nV -= 4; } if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) == 1) { fSet = true; ECDSA_SIG_free(sig); return true; } ECDSA_SIG_free(sig); return false; }
static int test_builtin(void) { EC_builtin_curve *curves = NULL; size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; ECDSA_SIG *ecdsa_sig = NULL, *modified_sig = NULL; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; const unsigned char *sig_ptr; unsigned char *sig_ptr2; unsigned char *raw_buf = NULL; const BIGNUM *sig_r, *sig_s; BIGNUM *modified_r = NULL, *modified_s = NULL; BIGNUM *unmodified_r = NULL, *unmodified_s = NULL; unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ if (!TEST_true(RAND_bytes(digest, 20)) || !TEST_true(RAND_bytes(wrong_digest, 20))) goto builtin_err; /* create and verify a ecdsa signature with every available curve */ /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len)) || !TEST_true(EC_get_builtin_curves(curves, crv_len))) goto builtin_err; /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4 || nid == NID_X25519) continue; /* create new ecdsa key (== EC_KEY) */ if (!TEST_ptr(eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(eckey, group))) goto builtin_err; EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) { /* drop the curve */ EC_KEY_free(eckey); eckey = NULL; continue; } TEST_info("testing %s", OBJ_nid2sn(nid)); /* create key */ if (!TEST_true(EC_KEY_generate_key(eckey))) goto builtin_err; /* create second key */ if (!TEST_ptr(wrong_eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(wrong_eckey, group))) goto builtin_err; EC_GROUP_free(group); if (!TEST_true(EC_KEY_generate_key(wrong_eckey))) goto builtin_err; /* check key */ if (!TEST_true(EC_KEY_check_key(eckey))) goto builtin_err; /* create signature */ sig_len = ECDSA_size(eckey); if (!TEST_ptr(signature = OPENSSL_malloc(sig_len)) || !TEST_true(ECDSA_sign(0, digest, 20, signature, &sig_len, eckey))) goto builtin_err; /* verify signature */ if (!TEST_int_eq(ECDSA_verify(0, digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* verify signature with the wrong key */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey), 1)) goto builtin_err; /* wrong digest */ if (!TEST_int_ne(ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* wrong length */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey), 1)) goto builtin_err; /* * Modify a single byte of the signature: to ensure we don't garble * the ASN1 structure, we read the raw signature and modify a byte in * one of the bignums directly. */ sig_ptr = signature; if (!TEST_ptr(ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len))) goto builtin_err; ECDSA_SIG_get0(ecdsa_sig, &sig_r, &sig_s); /* Store the two BIGNUMs in raw_buf. */ r_len = BN_num_bytes(sig_r); s_len = BN_num_bytes(sig_s); bn_len = (degree + 7) / 8; if (!TEST_false(r_len > bn_len) || !TEST_false(s_len > bn_len)) goto builtin_err; buf_len = 2 * bn_len; if (!TEST_ptr(raw_buf = OPENSSL_zalloc(buf_len))) goto builtin_err; BN_bn2bin(sig_r, raw_buf + bn_len - r_len); BN_bn2bin(sig_s, raw_buf + buf_len - s_len); /* Modify a single byte in the buffer. */ offset = raw_buf[10] % buf_len; dirt = raw_buf[11] ? raw_buf[11] : 1; raw_buf[offset] ^= dirt; /* Now read the BIGNUMs back in from raw_buf. */ if (!TEST_ptr(modified_sig = ECDSA_SIG_new())) goto builtin_err; if (!TEST_ptr(modified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(modified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, modified_r, modified_s))) { BN_free(modified_r); BN_free(modified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_false(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* Sanity check: undo the modification and verify signature. */ raw_buf[offset] ^= dirt; if (!TEST_ptr(unmodified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(unmodified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, unmodified_r, unmodified_s))) { BN_free(unmodified_r); BN_free(unmodified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_true(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* cleanup */ ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; ECDSA_SIG_free(modified_sig); modified_sig = NULL; OPENSSL_free(raw_buf); raw_buf = NULL; } ret = 1; builtin_err: EC_KEY_free(eckey); EC_KEY_free(wrong_eckey); ECDSA_SIG_free(ecdsa_sig); ECDSA_SIG_free(modified_sig); OPENSSL_free(signature); OPENSSL_free(raw_buf); OPENSSL_free(curves); return ret; }
void ecdsa_sigverify(val_context_t * ctx, const u_char *data, size_t data_len, const val_dnskey_rdata_t * dnskey, const val_rrsig_rdata_t * rrsig, val_astatus_t * key_status, val_astatus_t * sig_status) { char buf[1028]; size_t buflen = 1024; u_char sha_hash[MAX_DIGEST_LENGTH]; EC_KEY *eckey = NULL; BIGNUM *bn_x = NULL; BIGNUM *bn_y = NULL; ECDSA_SIG *ecdsa_sig; size_t hashlen = 0; ecdsa_sig = ECDSA_SIG_new(); memset(sha_hash, 0, sizeof(sha_hash)); val_log(ctx, LOG_DEBUG, "ecdsa_sigverify(): parsing the public key..."); if (rrsig->algorithm == ALG_ECDSAP256SHA256) { hashlen = SHA256_DIGEST_LENGTH; SHA256(data, data_len, sha_hash); eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); /* P-256 */ } else if (rrsig->algorithm == ALG_ECDSAP384SHA384) { hashlen = SHA384_DIGEST_LENGTH; SHA384(data, data_len, sha_hash); eckey = EC_KEY_new_by_curve_name(NID_secp384r1); /* P-384 */ } if (eckey == NULL) { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): could not create key for ECDSA group."); *key_status = VAL_AC_INVALID_KEY; goto err; }; /* * contruct an EC_POINT from the "Q" field in the * dnskey->public_key, dnskey->public_key_len */ if (dnskey->public_key_len != 2*hashlen) { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): dnskey length does not match expected size."); *key_status = VAL_AC_INVALID_KEY; goto err; } bn_x = BN_bin2bn(dnskey->public_key, hashlen, NULL); bn_y = BN_bin2bn(&dnskey->public_key[hashlen], hashlen, NULL); if (1 != EC_KEY_set_public_key_affine_coordinates(eckey, bn_x, bn_y)) { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): Error associating ECSA structure with key."); *key_status = VAL_AC_INVALID_KEY; goto err; } val_log(ctx, LOG_DEBUG, "ecdsa_sigverify(): SHA hash = %s", get_hex_string(sha_hash, hashlen, buf, buflen)); val_log(ctx, LOG_DEBUG, "ecdsa_sigverify(): verifying ECDSA signature..."); /* * contruct ECDSA signature from the "r" and "s" fileds in * rrsig->signature, rrsig->signature_len */ if (rrsig->signature_len != 2*hashlen) { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): Signature length does not match expected size."); *sig_status = VAL_AC_RRSIG_VERIFY_FAILED; goto err; } ECDSA_SIG_set0(ecdsa_sig, BN_bin2bn(rrsig->signature, hashlen, NULL), BN_bin2bn(&rrsig->signature[hashlen], hashlen, NULL)); if (ECDSA_do_verify(sha_hash, hashlen, ecdsa_sig, eckey) == 1) { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): returned SUCCESS"); *sig_status = VAL_AC_RRSIG_VERIFIED; } else { val_log(ctx, LOG_INFO, "ecdsa_sigverify(): returned FAILURE"); *sig_status = VAL_AC_RRSIG_VERIFY_FAILED; } /* Free all structures allocated */ err: if (ecdsa_sig) ECDSA_SIG_free(ecdsa_sig); if (bn_x) BN_free(bn_x); if (bn_y) BN_free(bn_y); if (eckey) EC_KEY_free(eckey); return; }
/* ARGSUSED */ int ssh_ecdsa_verify(const struct sshkey *key, const u_char *signature, size_t signaturelen, const u_char *data, size_t datalen, u_int compat) { ECDSA_SIG *sig = NULL; int hash_alg; u_char digest[SSH_DIGEST_MAX_LENGTH]; size_t dlen; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL, *sigbuf = NULL; char *ktype = NULL; if (key == NULL || key->ecdsa == NULL || sshkey_type_plain(key->type) != KEY_ECDSA || signature == NULL || signaturelen == 0) return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || (dlen = ssh_digest_bytes(hash_alg)) == 0) return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ if ((b = sshbuf_from(signature, signaturelen)) == NULL) return SSH_ERR_ALLOC_FAIL; if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || sshbuf_froms(b, &sigbuf) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { ret = SSH_ERR_KEY_TYPE_MISMATCH; goto out; } if (sshbuf_len(b) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } /* parse signature */ if ((sig = ECDSA_SIG_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } { BIGNUM *r=NULL, *s=NULL; if ((r = BN_new()) == NULL || (s = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out_rs; } if (sshbuf_get_bignum2(sigbuf, r) != 0 || sshbuf_get_bignum2(sigbuf, s) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out_rs; } if (ECDSA_SIG_set0(sig, r, s) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; out_rs: BN_free(r); BN_free(s); goto out; } r = s = NULL; } if (sshbuf_len(sigbuf) != 0) { ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; goto out; } if ((ret = ssh_digest_memory(hash_alg, data, datalen, digest, sizeof(digest))) != 0) goto out; switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { case 1: ret = 0; break; case 0: ret = SSH_ERR_SIGNATURE_INVALID; goto out; default: ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } out: explicit_bzero(digest, sizeof(digest)); sshbuf_free(sigbuf); sshbuf_free(b); ECDSA_SIG_free(sig); free(ktype); return ret; }
int jwt_verify_sha_pem(jwt_t *jwt, const char *head, const char *sig_b64) { unsigned char *sig = NULL; EVP_MD_CTX *mdctx = NULL; ECDSA_SIG *ec_sig = NULL; BIGNUM *ec_sig_r = NULL; BIGNUM *ec_sig_s = NULL; EVP_PKEY *pkey = NULL; const EVP_MD *alg; int type; int pkey_type; BIO *bufkey = NULL; int ret = 0; int 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; } sig = jwt_b64_decode(sig_b64, &slen); if (sig == NULL) VERIFY_ERROR(EINVAL); bufkey = BIO_new_mem_buf(jwt->key, jwt->key_len); if (bufkey == NULL) VERIFY_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_PUBKEY(bufkey, NULL, NULL, NULL); if (pkey == NULL) VERIFY_ERROR(EINVAL); pkey_type = EVP_PKEY_id(pkey); if (pkey_type != type) VERIFY_ERROR(EINVAL); /* Convert EC sigs back to ASN1. */ if (pkey_type == EVP_PKEY_EC) { unsigned int degree, bn_len; unsigned char *p; EC_KEY *ec_key; ec_sig = ECDSA_SIG_new(); if (ec_sig == NULL) VERIFY_ERROR(ENOMEM); /* Get the actual ec_key */ ec_key = EVP_PKEY_get1_EC_KEY(pkey); if (ec_key == NULL) VERIFY_ERROR(ENOMEM); degree = EC_GROUP_get_degree(EC_KEY_get0_group(ec_key)); EC_KEY_free(ec_key); bn_len = (degree + 7) / 8; if ((bn_len * 2) != slen) VERIFY_ERROR(EINVAL); ec_sig_r = BN_bin2bn(sig, bn_len, NULL); ec_sig_s = BN_bin2bn(sig + bn_len, bn_len, NULL); if (ec_sig_r == NULL || ec_sig_s == NULL) VERIFY_ERROR(EINVAL); ECDSA_SIG_set0(ec_sig, ec_sig_r, ec_sig_s); free(sig); slen = i2d_ECDSA_SIG(ec_sig, NULL); sig = malloc(slen); if (sig == NULL) VERIFY_ERROR(ENOMEM); p = sig; slen = i2d_ECDSA_SIG(ec_sig, &p); if (slen == 0) VERIFY_ERROR(EINVAL); } mdctx = EVP_MD_CTX_create(); if (mdctx == NULL) VERIFY_ERROR(ENOMEM); /* Initialize the DigestVerify operation using alg */ if (EVP_DigestVerifyInit(mdctx, NULL, alg, NULL, pkey) != 1) VERIFY_ERROR(EINVAL); /* Call update with the message */ if (EVP_DigestVerifyUpdate(mdctx, head, strlen(head)) != 1) VERIFY_ERROR(EINVAL); /* Now check the sig for validity. */ if (EVP_DigestVerifyFinal(mdctx, sig, slen) != 1) VERIFY_ERROR(EINVAL); jwt_verify_sha_pem_done: if (bufkey) BIO_free(bufkey); if (pkey) EVP_PKEY_free(pkey); if (mdctx) EVP_MD_CTX_destroy(mdctx); if (sig) free(sig); if (ec_sig) ECDSA_SIG_free(ec_sig); return ret; }