/* returns * 1: correct signature * 0: incorrect signature * -1: error */ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) { ECDSA_SIG *s; unsigned char *der = NULL; const unsigned char *p = sigbuf; int derlen = -1; int ret = -1; s = ECDSA_SIG_new(); if (s == NULL) return (ret); if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) goto err; /* Ensure signature uses DER and doesn't have trailing garbage */ derlen = i2d_ECDSA_SIG(s, &der); if (derlen != sig_len || memcmp(sigbuf, der, derlen)) goto err; ret = ECDSA_do_verify(dgst, dgst_len, s, eckey); err: freezero(der, derlen); ECDSA_SIG_free(s); return (ret); }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig) { if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on * error. But OpenSSL's own use of this function redundantly frees the * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a * clear contract for the function behaving the same way is more * conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *ecdsa) { struct pkcs11_key_data *pkd = NULL; CK_MECHANISM mech = { CKM_ECDSA, NULL_PTR, 0 }; CK_ULONG tlen = 0; CK_RV rv; #if OPENSSL_VERSION_NUMBER < 0x10100000L pkd = ECDSA_get_ex_data(ecdsa, pkcs11_ecdsa_key_idx); #else pkd = EC_KEY_get_ex_data(ecdsa, pkcs11_ecdsa_key_idx); #endif if((pkd != NULL) && ((rv = pkd->funcs->C_SignInit(pkd->session, &mech, pkd->key)) == CKR_OK)) { CK_BYTE_PTR buf = NULL; ECDSA_SIG *rval; BIGNUM *r, *s; int nlen; /* Make a call to C_Sign to find out the size of the signature */ rv = pkd->funcs->C_Sign(pkd->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen); if (rv != CKR_OK) { return NULL; } if ((buf = malloc(tlen)) == NULL) { return NULL; } rv = pkd->funcs->C_Sign(pkd->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen); if (rv != CKR_OK) { free(buf); return NULL; } if ((rval = ECDSA_SIG_new()) != NULL) { /* * ECDSA signature is 2 large integers of same size returned * concatenated by PKCS#11, we separate them to create an * ECDSA_SIG for OpenSSL. */ nlen = tlen / 2; #if OPENSSL_VERSION_NUMBER >= 0x10100000L ECDSA_SIG_get0(&r, &s, rval); #else r = rval->r; s = rval->s; #endif BN_bin2bn(&buf[0], nlen, r); BN_bin2bn(&buf[nlen], nlen, s); } free(buf); return rval; } else { return NULL; } }
int verification( const unsigned char m[SHORTHASH_BYTES],const unsigned long long mlen, const unsigned char sm[SIGNATURE_BYTES],const unsigned long long smlen, const unsigned char pk[PUBLICKEY_BYTES],const unsigned long long pklen ) { unsigned char h[20]; EC_GROUP *group; EC_KEY *k; EC_POINT *kxy; BIGNUM *kx; BIGNUM *ky; ECDSA_SIG *rs; int len; if (smlen != SIGNATURE_BYTES) return -1; if (mlen > SHORTHASH_BYTES) return -1; SHA1(m,mlen,h); group = EC_GROUP_new_by_curve_name(NID); if (!group) return -1; kx = BN_new(); if (!kx) return -1; ky = BN_new(); if (!ky) { BN_free(kx); return -1; } kxy = EC_POINT_new(group); if (!kxy) { BN_free(ky); BN_free(kx); return -1; } k = EC_KEY_new(); if (!k) { EC_POINT_free(kxy); BN_free(ky); BN_free(kx); return -1; } rs = ECDSA_SIG_new(); if (!rs) { EC_KEY_free(k); EC_POINT_free(kxy); BN_free(ky); BN_free(kx); return -1; } if (!EC_KEY_set_group(k,group)) goto error; if (!BN_bin2bn(pk,PRIME_BYTES,kx)) goto error; pk += PRIME_BYTES; if (!BN_bin2bn(pk,PRIME_BYTES,ky)) goto error; #ifdef PRIME_FIELD if (!EC_POINT_set_affine_coordinates_GFp(group,kxy,kx,ky,0)) goto error; #else if (!EC_POINT_set_affine_coordinates_GF2m(group,kxy,kx,ky,0)) goto error; #endif if (!EC_KEY_set_public_key(k,kxy)) goto error; if (!BN_bin2bn(sm,PRIME_BYTES,rs->r)) goto error; sm += PRIME_BYTES; if (!BN_bin2bn(sm,PRIME_BYTES,rs->s)) goto error; len = ECDSA_do_verify(h,20,rs,k); ECDSA_SIG_free(rs); EC_KEY_free(k); EC_POINT_free(kxy); BN_free(ky); BN_free(kx); if (len == 1) return 0; if (len == 0) return -100; return -1; error: ECDSA_SIG_free(rs); EC_KEY_free(k); EC_POINT_free(kxy); BN_free(ky); BN_free(kx); return -1; }
/** * Setup the ECDSA signature in its encoding that the library wants. * Converts from plain numbers to ASN formatted. * @param sig: input is signature, output alloced ptr (unless failure). * caller must free alloced ptr if this routine returns true. * @param len: input is initial siglen, output is output len. * @return false on failure. */ static int setup_ecdsa_sig(unsigned char** sig, unsigned int* len) { ECDSA_SIG* ecdsa_sig; int newlen; int bnsize = (int)((*len)/2); /* if too short or not even length, fails */ if(*len < 16 || bnsize*2 != (int)*len) return 0; /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ ecdsa_sig = ECDSA_SIG_new(); if(!ecdsa_sig) return 0; ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r); ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s); if(!ecdsa_sig->r || !ecdsa_sig->s) { ECDSA_SIG_free(ecdsa_sig); return 0; } /* spool it into ASN format */ *sig = NULL; newlen = i2d_ECDSA_SIG(ecdsa_sig, sig); if(newlen <= 0) { ECDSA_SIG_free(ecdsa_sig); free(*sig); return 0; } *len = (unsigned int)newlen; ECDSA_SIG_free(ecdsa_sig); return 1; }
public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical ) { int nV = c.data[0]; if (nV<27 || nV>=35) FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); ECDSA_SIG *sig = ECDSA_SIG_new(); BN_bin2bn(&c.data[1],32,sig->r); BN_bin2bn(&c.data[33],32,sig->s); if( check_canonical ) { FC_ASSERT( is_canonical( c ), "signature is not canonical" ); } my->_key = EC_KEY_new_by_curve_name(NID_secp256k1); if (nV >= 31) { EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED ); nV -= 4; // fprintf( stderr, "compressed\n" ); } if (detail::public_key_impl::ECDSA_SIG_recover_key_GFp(my->_key, sig, (unsigned char*)&digest, sizeof(digest), nV - 27, 0) == 1) { ECDSA_SIG_free(sig); return; } ECDSA_SIG_free(sig); FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); }
// 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(); BN_bin2bn(&vchSig[1],32,sig->r); BN_bin2bn(&vchSig[33],32,sig->s); 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; } return false; }
/** * 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; }
/*! * \brief Finish the signing and write out the ECDSA signature. * \see rsa_sign_write */ static int ecdsa_sign_write(const knot_dnssec_sign_context_t *context, uint8_t *signature, size_t signature_size) { assert(context); assert(signature); size_t output_size = ecdsa_sign_size(context->key); if (output_size != signature_size) { return KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE; } // create raw signature uint8_t *raw_signature = NULL; size_t raw_size = 0; int result = sign_alloc_and_write(context, &raw_signature, &raw_size); if (result != KNOT_EOK) { return result; } // decode signature ECDSA_SIG *decoded = ECDSA_SIG_new(); if (!decoded) { free(raw_signature); return KNOT_ENOMEM; } const uint8_t *decode_scan = raw_signature; if (!d2i_ECDSA_SIG(&decoded, &decode_scan, (long)raw_size)) { ECDSA_SIG_free(decoded); free(raw_signature); return KNOT_DNSSEC_EDECODE_RAW_SIGNATURE; } free(raw_signature); // convert to format defined by RFC 6605 (EC DSA for DNSSEC) // R and S parameters are encoded in halves of the output signature uint8_t *signature_r; uint8_t *signature_s; size_t param_size = output_size / 2; memset(signature, '\0', output_size); signature_r = signature + param_size - BN_num_bytes(decoded->r); signature_s = signature + 2 * param_size - BN_num_bytes(decoded->s); BN_bn2bin(decoded->r, signature_r); BN_bn2bin(decoded->s, signature_s); ECDSA_SIG_free(decoded); return KNOT_EOK; }
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(); BN_bin2bn(&p64[0], 32, sig->r); BN_bin2bn(&p64[32], 32, sig->s); bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1; ECDSA_SIG_free(sig); return ret; }
int el_verify_license_key(el_context_t ctxt, const char *licenseKey, const char *name) { // TODO: change this back to use C99 variable length arrays once Visual C++ // can deal with it (2013 still can't) ECDSA_SIG *signature = NULL; uint8_t *signatureData = NULL; uint8_t *digest = NULL; if (!licenseKey || !strlen(licenseKey) || !name || !strlen(name)) return 0; // TODO: blocked keys checking int signatureLength = el_base32_decode_buffer_size(strlen(licenseKey)); signatureData = malloc(signatureLength); signatureLength = el_base32_decode(licenseKey, signatureData, signatureLength); // Check length of signature before verifying if (signatureLength != ctxt->digestLength * 2) { free(signatureData); return 0; } signature = ECDSA_SIG_new(); if (!signature) { free(signatureData); return 0; } size_t partLen = signatureLength / 2; signature->r = BN_bin2bn(signatureData, partLen, signature->r); signature->s = BN_bin2bn(signatureData + partLen, partLen, signature->s); if (!signature->r || !signature->s) { free(signatureData); ECDSA_SIG_free(signature); return 0; } digest = malloc(ctxt->digestLength); el_compute_digest(name, digest, ctxt->digestLength); int result = ECDSA_do_verify(digest, ctxt->digestLength, signature, ctxt->ecKey) == 1; free(signatureData); free(digest); ECDSA_SIG_free(signature); return result; }
// Credit: https://github.com/ppcoin/ppcoin/pull/101/files bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSigParam) { // Prevent the problem described here: // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html // by removing the extra length bytes std::vector<unsigned char> vchSig(vchSigParam.begin(), vchSigParam.end()); if (vchSig.size() > 1 && vchSig[1] & 0x80) { unsigned char nLengthBytes = vchSig[1] & 0x7f; if (vchSig.size() < 2 + nLengthBytes) return false; if (nLengthBytes > 4) { unsigned char nExtraBytes = nLengthBytes - 4; for (unsigned char i = 0; i < nExtraBytes; i++) if (vchSig[2 + i]) return false; vchSig.erase(vchSig.begin() + 2, vchSig.begin() + 2 + nExtraBytes); vchSig[1] = 0x80 | (nLengthBytes - nExtraBytes); } } if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on * error. But OpenSSL's own use of this function redundantly frees the * result. As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a * clear contract for the function behaving the same way is more * conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
/** * 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 */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L key = (PKCS11_KEY *)EC_KEY_get_ex_data(ec, ec_ex_index); #else key = (PKCS11_KEY *)ECDSA_get_ex_data(ec, ec_ex_index); #endif if (key == NULL) { PKCS11err(PKCS11_F_PKCS11_EC_KEY_SIGN, PKCS11_ALIEN_KEY); return NULL; } /* TODO: Add an atfork check */ /* 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; sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L ECDSA_SIG_get0(&r, &s, sig); #else r = sig->r; s = sig->s; #endif BN_bin2bn(sigret, siglen/2, r); BN_bin2bn(sigret + siglen/2, siglen/2, s); return sig; }
static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen, const BIGNUM *inv, const BIGNUM *r, EC_KEY * ec) { unsigned char sigret[512]; /* HACK for now */ ECDSA_SIG * sig = NULL; PKCS11_KEY * key = NULL; unsigned int siglen; int nLen = 48; /* HACK */ int rv; #if OPENSSL_VERSION_NUMBER >= 0x10100000L key = (PKCS11_KEY *) EC_KEY_get_ex_data(ec, ec_key_ex_index); #else key = (PKCS11_KEY *) ECDSA_get_ex_data(ec, ecdsa_ex_index); #endif if (key == NULL) return NULL; siglen = sizeof(sigret); rv = PKCS11_ecdsa_sign(dgst, dlen, sigret, &siglen, key); nLen = siglen / 2; if (rv > 0) { sig = ECDSA_SIG_new(); if (sig) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L /* * OpenSSL 1.1 does not have a way to allocate r and s * in ECDSA_SIG as it is now hidden. * Will us dummy ASN1 so r and s are allocated then * use ECDSA_SIG_get0 to get access to r and s * can then update r annd s */ const unsigned char *a; unsigned char dasn1[8] = {0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}; BIGNUM *r; BIGNUM *s; a = dasn1; d2i_ECDSA_SIG(&sig, &a, 8); ECDSA_SIG_get0(&r, &s, sig); BN_bin2bn(&sigret[0], nLen, r); BN_bin2bn(&sigret[nLen], nLen, s); #else BN_bin2bn(&sigret[0], nLen, sig->r); BN_bin2bn(&sigret[nLen], nLen, sig->s); #endif } } return sig; }
static isc_result_t opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { isc_result_t ret; dst_key_t *key = dctx->key; int status; unsigned char *cp = sig->base; ECDSA_SIG *ecdsasig = NULL; EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; EVP_PKEY *pkey = key->keydata.pkey; EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); unsigned int dgstlen, siglen; unsigned char digest[EVP_MAX_MD_SIZE]; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if (eckey == NULL) return (ISC_R_FAILURE); if (key->key_alg == DST_ALG_ECDSA256) siglen = DNS_SIG_ECDSA256SIZE; else siglen = DNS_SIG_ECDSA384SIZE; if (sig->length != siglen) return (DST_R_VERIFYFAILURE); if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) DST_RET (ISC_R_FAILURE); ecdsasig = ECDSA_SIG_new(); if (ecdsasig == NULL) DST_RET (ISC_R_NOMEMORY); ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL); cp += siglen / 2; ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL); /* cp += siglen / 2; */ status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey); if (status != 1) DST_RET (dst__openssl_toresult(DST_R_VERIFYFAILURE)); ret = ISC_R_SUCCESS; err: if (ecdsasig != NULL) ECDSA_SIG_free(ecdsasig); if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
/* returns * 1: correct signature * 0: incorrect signature * -1: error */ int ECDSA_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey) { ECDSA_SIG *s; int ret=-1; s = ECDSA_SIG_new(); if (s == NULL) return(ret); if (d2i_ECDSA_SIG(&s, &sigbuf, sig_len) == NULL) goto err; ret=ECDSA_do_verify(dgst, dgst_len, s, eckey); err: ECDSA_SIG_free(s); return(ret); }
/*! * \brief Verify the DNSSEC signature for supplied data and ECDSA algorithm. * \see any_sign_verify */ static int ecdsa_sign_verify(const knot_dnssec_sign_context_t *context, const uint8_t *signature, size_t signature_size) { assert(context); assert(signature); if (signature_size != ecdsa_sign_size(context->key)) { return KNOT_EINVAL; } // see ecdsa_sign_write() for conversion details size_t parameter_size = signature_size / 2; const uint8_t *signature_r = signature; const uint8_t *signature_s = signature + parameter_size; ECDSA_SIG *decoded = ECDSA_SIG_new(); if (!decoded) { return KNOT_ENOMEM; } decoded->r = BN_bin2bn(signature_r, parameter_size, decoded->r); decoded->s = BN_bin2bn(signature_s, parameter_size, decoded->s); size_t max_size = EVP_PKEY_size(context->key->data->private_key); uint8_t *raw_signature = malloc(max_size); if (!raw_signature) { ECDSA_SIG_free(decoded); return KNOT_ENOMEM; } uint8_t *raw_write = raw_signature; int raw_size = i2d_ECDSA_SIG(decoded, &raw_write); if (raw_size < 0) { free(raw_signature); ECDSA_SIG_free(decoded); return KNOT_DNSSEC_EDECODE_RAW_SIGNATURE; } assert(raw_write == raw_signature + raw_size); int result = any_sign_verify(context, raw_signature, raw_size); ECDSA_SIG_free(decoded); free(raw_signature); return result; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSigParam) { // Fix invalid signature with crafted length by removing extra length bytes std::vector<unsigned char> vchSig(vchSigParam.begin(), vchSigParam.end()); if (vchSig.size() > 1 && vchSig[1] & 0x80) { unsigned char nLengthBytes = vchSig[1] & 0x7f; if (vchSig.size() < 2 + nLengthBytes) // Avoid invalid memory access on crafted signature return false; if (nLengthBytes > 4) { unsigned char nExtraBytes = nLengthBytes - 4; for (unsigned char i = 0; i < nExtraBytes; i++) if (vchSig[2 + i]) return false; vchSig.erase(vchSig.begin() + 2, vchSig.begin() + 2 + nExtraBytes); vchSig[1] = 0x80 | (nLengthBytes - nExtraBytes); } } if (vchSig.empty()) return false; // New versions of OpenSSL will reject non-canonical DER signatures. De/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; assert(norm_sig); if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL) { /* As of OpenSSL 1.0.0p d2i_ECDSA_SIG frees and nulls the pointer on error. * But OpenSSL's own use of this function redundantly frees the result. * As ECDSA_SIG_free(NULL) is a no-op, and in the absence of a clear contract for the function behaving the same way is more conservative. */ ECDSA_SIG_free(norm_sig); return false; } int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
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; }
ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) { ECDSA_SIG *ret = ECDSA_SIG_new(); if (ret == NULL) { return NULL; } CBS child; if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || !BN_parse_asn1_unsigned(&child, ret->r) || !BN_parse_asn1_unsigned(&child, ret->s) || CBS_len(&child) != 0) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE); ECDSA_SIG_free(ret); return NULL; } return ret; }
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig) { // New versions of OpenSSL will reject non-canonical DER signatures. de/re-serialize first. unsigned char *norm_der = NULL; ECDSA_SIG *norm_sig = ECDSA_SIG_new(); const unsigned char* sigptr = &vchSig[0]; d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()); int derlen = i2d_ECDSA_SIG(norm_sig, &norm_der); ECDSA_SIG_free(norm_sig); if (derlen <= 0) return false; // -1 = error, 0 = bad sig, 1 = good bool ret = ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1; OPENSSL_free(norm_der); return ret; }
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; }
static int openssl_ecdsa_verify(lua_State*L) { size_t l; int ret; EC_KEY* ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key"); const char* dgst = luaL_checklstring(L, 2, &l); BIGNUM *r = CHECK_OBJECT(3, BIGNUM, "openssl.bn"); BIGNUM *s = CHECK_OBJECT(4, BIGNUM, "openssl.bn"); ECDSA_SIG* sig = ECDSA_SIG_new(); BN_copy(sig->r, r); BN_copy(sig->s, s); ret = ECDSA_do_verify((const unsigned char*)dgst, l, sig, ec); if (ret == -1) lua_pushnil(L); else lua_pushboolean(L, ret); ECDSA_SIG_free(sig); return 1; }
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 ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0, i; BIGNUM *kinv=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; const BIGNUM *priv_key; ecdsa = ecdsa_check(eckey); group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL || ecdsa == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); return NULL; } #ifdef OPENSSL_FIPS if (!fips_check_ec_prng(eckey)) return NULL; #endif ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; } i = BN_num_bits(order); /* Need to truncate digest if it is too long: first truncate whole * bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7)/8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } do { if (in_kinv == NULL || in_r == NULL) { if (!ecdsa->meth->ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* if kinv and r have been supplied by the caller * don't to generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else /* s != 0 => we have a valid signature */ break; } while (1); ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } if (ctx) BN_CTX_free(ctx); if (m) BN_clear_free(m); if (tmp) BN_clear_free(tmp); if (order) BN_free(order); if (kinv) BN_clear_free(kinv); return ret; }
// Verification functions bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); if (lowerMechanism.compare("ecdsa")) { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); return false; } // Check if the private key is the right type if (!publicKey->isOfType(OSSLECPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey; EC_KEY* eckey = pk->getOSSLKey(); if (eckey == NULL) { ERROR_MSG("Could not get the OpenSSL public key"); return false; } // Perform the verify operation size_t len = pk->getOrderLength(); if (len == 0) return false; if (signature.size() != 2 * len) return false; ECDSA_SIG* sig = ECDSA_SIG_new(); if (sig == NULL) return false; if (sig->r != NULL) BN_clear_free(sig->r); const unsigned char *s = signature.const_byte_str(); sig->r = BN_bin2bn(s, len, NULL); if (sig->s != NULL) BN_clear_free(sig->s); sig->s = BN_bin2bn(s + len, len, NULL); if (sig->r == NULL || sig->s == NULL) { ECDSA_SIG_free(sig); return false; } int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey); if (ret != 1) { if (ret < 0) ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error()); ECDSA_SIG_free(sig); return false; } ECDSA_SIG_free(sig); return true; }
int ssh_ecdsa_verify(EC_KEY *key, ssh_keytype keytype, u_char *signature, u_int signaturelen, u_char *data, u_int datalen) { ECDSA_SIG *sig; const EVP_MD *evp_md; EVP_MD_CTX md; unsigned char digest[EVP_MAX_MD_SIZE], *sigblob; unsigned int len, dlen; int ret, nid = NID_undef; char *ptr; OpenSSL_add_all_digests(); if (key == NULL) { return -2; } ptr = signature; len = get_uint32_MSBfirst(ptr); ptr += 4; if (strncmp(get_ssh_keytype_name(keytype), ptr, len) != 0) { return -3; } ptr += len; len = get_uint32_MSBfirst(ptr); ptr += 4; sigblob = ptr; ptr += len; /* parse signature */ if ((sig = ECDSA_SIG_new()) == NULL) return -4; if ((sig->r = BN_new()) == NULL) return -5; if ((sig->s = BN_new()) == NULL) return -6; buffer_get_bignum2(&sigblob, sig->r); buffer_get_bignum2(&sigblob, sig->s); if (sigblob != ptr) { return -7; } /* hash the data */ nid = keytype_to_hash_nid(keytype); if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { return -8; } EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); ret = ECDSA_do_verify(digest, dlen, sig, key); memset(digest, 'd', sizeof(digest)); ECDSA_SIG_free(sig); return ret; }
static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey) { int ok = 0; BIGNUM *kinv=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL; const BIGNUM *ckinv; BN_CTX *ctx = NULL; const EC_GROUP *group; ECDSA_SIG *ret; ECDSA_DATA *ecdsa; const BIGNUM *priv_key; ecdsa = ecdsa_check(eckey); group = EC_KEY_get0_group(eckey); priv_key = EC_KEY_get0_private_key(eckey); if (group == NULL || priv_key == NULL || ecdsa == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); return NULL; } ret = ECDSA_SIG_new(); if (!ret) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); return NULL; } s = ret->s; if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL || (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB); goto err; } if (8 * dgst_len > BN_num_bits(order)) { /* XXX * * Should provide for optional hash truncation: * Keep the BN_num_bits(order) leftmost bits of dgst * (see March 2006 FIPS 186-3 draft, which has a few * confusing errors in this part though) */ ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); goto err; } if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } do { if (in_kinv == NULL || in_r == NULL) { if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB); goto err; } ckinv = kinv; } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE); goto err; } } if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_add_quick(s, tmp, m, order)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (!BN_mod_mul(s, s, ckinv, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB); goto err; } if (BN_is_zero(s)) { /* if kinv and r have been supplied by the caller * don't to generate new kinv and r values */ if (in_kinv != NULL && in_r != NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES); goto err; } } else /* s != 0 => we have a valid signature */ break; } while (1); ok = 1; err: if (!ok) { ECDSA_SIG_free(ret); ret = NULL; } if (ctx) BN_CTX_free(ctx); if (m) BN_clear_free(m); if (tmp) BN_clear_free(tmp); if (order) BN_free(order); if (kinv) BN_clear_free(kinv); return ret; }