// create a compact signature (65 bytes), which allows reconstructing the used public key
// The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
// The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
//                  0x1D = second key with even y, 0x1E = second key with odd y
bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
{
    bool fOk = false;
    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
    if (sig==NULL)
        return false;
    vchSig.clear();
    vchSig.resize(65,0);
    int nBitsR = BN_num_bits(sig->r);
    int nBitsS = BN_num_bits(sig->s);
    if (nBitsR <= 256 && nBitsS <= 256)
    {
        int nRecId = -1;
        for (int i=0; i<4; i++)
        {
            CKey keyRec;
            keyRec.fSet = true;
            if (fCompressedPubKey)
                keyRec.SetCompressedPubKey();
            if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1)
                if (keyRec.GetPubKey() == this->GetPubKey())
                {
                    nRecId = i;
                    break;
                }
        }

        if (nRecId == -1)
        {
            ECDSA_SIG_free(sig);
            throw key_error("CKey::SignCompact() : unable to construct recoverable key");
        }

        vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
        BN_bn2bin(sig->r,&vchSig[33-(nBitsR+7)/8]);
        BN_bn2bin(sig->s,&vchSig[65-(nBitsS+7)/8]);
        fOk = true;
    }
    ECDSA_SIG_free(sig);
    return fOk;
}
// Signing functions
bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
		     ByteString& signature, const AsymMech::Type mechanism,
		     const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{
	if (mechanism != AsymMech::ECDSA)
	{
		ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
		return false;
	}

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

		return false;
	}

	OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey;
	EC_KEY* eckey = pk->getOSSLKey();

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

		return false;
	}

	// Use the OpenSSL implementation and not any engine
	ECDSA_set_method(eckey, ECDSA_OpenSSL());

	// Perform the signature operation
	size_t len = pk->getOrderLength();
	if (len == 0)
	{
		ERROR_MSG("Could not get the order length");
		return false;
	}
	signature.resize(2 * len);
	memset(&signature[0], 0, 2 * len);
	ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
	if (sig == NULL)
	{
		ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error());
		return false;
	}
	// Store the 2 values with padding
	BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]);
	BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]);
	ECDSA_SIG_free(sig);
	return true;
}
Beispiel #3
0
ECDSA_SIG *ECDSA_SIG_new(void) {
  ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
  if (sig == NULL) {
    return NULL;
  }
  sig->r = BN_new();
  sig->s = BN_new();
  if (sig->r == NULL || sig->s == NULL) {
    ECDSA_SIG_free(sig);
    return NULL;
  }
  return sig;
}
Beispiel #4
0
// 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 isc_result_t
opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
	isc_result_t ret;
	dst_key_t *key = dctx->key;
	isc_region_t r;
	ECDSA_SIG *ecdsasig;
	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;

	isc_buffer_availableregion(sig, &r);
	if (r.length < siglen)
		DST_RET(ISC_R_NOSPACE);

	if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen))
		DST_RET(dst__openssl_toresult3(dctx->category,
					       "EVP_DigestFinal",
					       ISC_R_FAILURE));

	ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey);
	if (ecdsasig == NULL)
		DST_RET(dst__openssl_toresult3(dctx->category,
					       "ECDSA_do_sign",
					       DST_R_SIGNFAILURE));
	BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2);
	r.base += siglen / 2;
	BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2);
	r.base += siglen / 2;
	ECDSA_SIG_free(ecdsasig);
	isc_buffer_add(sig, siglen);
	ret = ISC_R_SUCCESS;

 err:
	if (eckey != NULL)
		EC_KEY_free(eckey);
	return (ret);
}
Beispiel #6
0
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);
}
Beispiel #7
0
/* 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);
	}
Beispiel #8
0
int
ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
    const u_char *data, u_int datalen)
{
	ECDSA_SIG *sig;
	const EVP_MD *evp_md;
	EVP_MD_CTX md;
	u_char digest[EVP_MAX_MD_SIZE];
	u_int len, dlen;
	Buffer b, bb;

	if (key == NULL || key->ecdsa == NULL ||
	    (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) {
		error("%s: no ECDSA key", __func__);
		return -1;
	}
	evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid);
	EVP_DigestInit(&md, evp_md);
	EVP_DigestUpdate(&md, data, datalen);
	EVP_DigestFinal(&md, digest, &dlen);

	sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
	memset(digest, 'd', sizeof(digest));

	if (sig == NULL) {
		error("%s: sign failed", __func__);
		return -1;
	}

	buffer_init(&bb);
	buffer_put_bignum2(&bb, sig->r);
	buffer_put_bignum2(&bb, sig->s);
	ECDSA_SIG_free(sig);

	buffer_init(&b);
	buffer_put_cstring(&b, key_ssh_name_plain(key));
	buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
	buffer_free(&bb);
	len = buffer_len(&b);
	if (lenp != NULL)
		*lenp = len;
	if (sigp != NULL) {
		*sigp = xmalloc(len);
		memcpy(*sigp, buffer_ptr(&b), len);
	}
	buffer_free(&b);

	return 0;
}
Beispiel #9
0
int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
                    unsigned char *sig, unsigned int *siglen,
                    const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
{
    ECDSA_SIG *s;
    RAND_seed(dgst, dlen);
    s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
    if (s == NULL) {
        *siglen = 0;
        return 0;
    }
    *siglen = i2d_ECDSA_SIG(s, &sig);
    ECDSA_SIG_free(s);
    return 1;
}
Beispiel #10
0
static int openssl_ecdsa_sign(lua_State*L)
{
  EC_KEY* ec = CHECK_OBJECT(1, EC_KEY, "openssl.ec_key");
  size_t l;
  const char* s = luaL_checklstring(L, 2, &l);
  ECDSA_SIG* sig = ECDSA_do_sign((const unsigned char*)s, l, ec);
  if (sig)
  {
    PUSH_BN(BN_dup(sig->r));
    PUSH_BN(BN_dup(sig->s));
    ECDSA_SIG_free(sig);
    return 2;
  }
  return 0;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
void getSigRaw(ecc_signature_t *sigraw, char *inFile)
{
	ECDSA_SIG* signature;
	int fdin;
	struct stat s;
	void *infile;
	unsigned char outbuf[2*EC_COORDBYTES];
	int r, rlen, roff, slen, soff;
	const BIGNUM *sr, *ss;

	fdin = open(inFile, O_RDONLY);
	assert(fdin > 0);
	r = fstat(fdin, &s);
	assert(r==0);

	infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
	assert(infile);

	signature = d2i_ECDSA_SIG(NULL, (const unsigned char **) &infile, 7 + 2*EC_COORDBYTES);

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

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	ECDSA_SIG_get0(signature, &sr, &ss);
#else
	sr = signature->r;
	ss = signature->s;
#endif
	rlen = BN_num_bytes(sr);
	roff = 66 - rlen;
	BN_bn2bin(sr, &outbuf[roff]);

	slen = BN_num_bytes(ss);
	soff = 66 + (66 - slen);
	BN_bn2bin(sr, &outbuf[soff]);

	if (debug)
		printBytes((char *)"sig (RAW)    = ", outbuf, sizeof(outbuf), 32);

	memcpy(*sigraw, outbuf, 2*EC_COORDBYTES);

	ECDSA_SIG_free(signature);
	close(fdin);

	return;
}
Beispiel #14
0
ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) {
  if (len < 0) {
    return NULL;
  }
  CBS cbs;
  CBS_init(&cbs, *inp, (size_t)len);
  ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs);
  if (ret == NULL) {
    return NULL;
  }
  if (out != NULL) {
    ECDSA_SIG_free(*out);
    *out = ret;
  }
  *inp = CBS_data(&cbs);
  return ret;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
// Signing functions
bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, 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 (!privateKey->isOfType(OSSLECPrivateKey::type))
	{
		ERROR_MSG("Invalid key type supplied");

		return false;
	}

	OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey;
	EC_KEY* eckey = pk->getOSSLKey();

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

		return false;
	}

	// Perform the signature operation
	size_t len = pk->getOrderLength();
	if (len == 0)
		return false;
	signature.resize(2 * len);
	memset(&signature[0], 0, 2 * len);
	ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
	if (sig == NULL)
		return false;
	// Store the 2 values with padding
	BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]);
	BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]);
	ECDSA_SIG_free(sig);
	return true;
}
Beispiel #18
0
Datei: jws.c Projekt: cisco/cjose
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;
}
Beispiel #19
0
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
    if ( fUseOld044Rules )
    {
        unsigned int nSize = ECDSA_size(pkey);
        vchSig.resize(nSize); // Make sure it is big enough
        if (!ECDSA_sign(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], &nSize, pkey))
        {
            vchSig.clear();
            return false;
        }
        vchSig.resize(nSize); // Shrink to fit actual size
        return true;
    }
    vchSig.clear();
    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
    if (sig==NULL)
        return false;
    const EC_GROUP *group = EC_KEY_get0_group(pkey);
    CBigNum order, halforder;
    EC_GROUP_get_order(group, &order, NULL);
    BN_rshift1(&halforder, &order);
    // enforce low S values, by negating the value (modulo the order) if above order/2.
    if (BN_cmp(sig->s, &halforder) > 0) 
    {
        BN_sub(sig->s, &order, sig->s);
    }
    unsigned int nSize = ECDSA_size(pkey);
    vchSig.resize(nSize); // Make sure it is big enough

    unsigned char *pos = &vchSig[0];
    nSize = i2d_ECDSA_SIG(sig, &pos);
    ECDSA_SIG_free(sig);
    vchSig.resize(nSize); // Shrink to fit actual size
    // Testing our new signature
    if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) 
    {
        vchSig.clear();
        return false;
    }
    return true;
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
void ssh_signature_free(ssh_signature sig)
{
    if (sig == NULL) {
        return;
    }

    switch(sig->type) {
        case SSH_KEYTYPE_DSS:
#ifdef HAVE_LIBGCRYPT
            gcry_sexp_release(sig->dsa_sig);
#elif defined HAVE_LIBCRYPTO
            DSA_SIG_free(sig->dsa_sig);
#endif
            break;
        case SSH_KEYTYPE_RSA:
        case SSH_KEYTYPE_RSA1:
#ifdef HAVE_LIBGCRYPT
            gcry_sexp_release(sig->rsa_sig);
#elif defined HAVE_LIBCRYPTO
            SAFE_FREE(sig->rsa_sig);
#endif
            break;
        case SSH_KEYTYPE_ECDSA:
#ifdef HAVE_GCRYPT_ECC
            gcry_sexp_release(sig->ecdsa_sig);
#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ECC)
            ECDSA_SIG_free(sig->ecdsa_sig);
#endif
            break;
        case SSH_KEYTYPE_ED25519:
            SAFE_FREE(sig->ed25519_sig);
            break;
        case SSH_KEYTYPE_DSS_CERT01:
        case SSH_KEYTYPE_RSA_CERT01:
        case SSH_KEYTYPE_UNKNOWN:
            break;
    }

    SAFE_FREE(sig);
}
Beispiel #23
0
int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
                  uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
                  const BIGNUM *r, const EC_KEY *eckey) {
  int ret = 0;
  ECDSA_SIG *s = NULL;

  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
    *sig_len = 0;
    goto err;
  }

  s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey);
  if (s == NULL) {
    *sig_len = 0;
    goto err;
  }

  CBB cbb;
  CBB_zero(&cbb);
  size_t len;
  if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) ||
      !ECDSA_SIG_marshal(&cbb, s) ||
      !CBB_finish(&cbb, NULL, &len)) {
    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
    CBB_cleanup(&cbb);
    *sig_len = 0;
    goto err;
  }
  *sig_len = (unsigned)len;
  ret = 1;

err:
  ECDSA_SIG_free(s);
  return ret;
}
Beispiel #24
0
// 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;
}
Beispiel #25
0
/*-
 * returns
 *      1: correct signature
 *      0: incorrect signature
 *     -1: error
 */
int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
                      const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
{
    ECDSA_SIG *s;
    const unsigned char *p = sigbuf;
    unsigned char *der = NULL;
    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) != 0)
        goto err;
    ret = ECDSA_do_verify(dgst, dgst_len, s, eckey);
 err:
    OPENSSL_clear_free(der, derlen);
    ECDSA_SIG_free(s);
    return (ret);
}
Beispiel #26
0
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;
}
Beispiel #27
0
int main (int argc, const char * argv[]) {
	
	EC_KEY *eckey;

	unsigned int curve;
	size_t digest_len;
	
	char name[1024], curve_name[200], pubkey[1024], privkey[1024];

	if (!read_params(name, 1024, curve_name, 200, pubkey, 1024, privkey, 1024))
		return ERR_STDIN_READ;
	
	///*debug*/printf("%s\n%s\n%s\n%s\n", name, curve_name, pubkey, privkey);
	
	// Get curve type and digest_len
	if (strcmp(curve_name, "secp112r1") == 0) {
		curve = NID_secp112r1;
		digest_len = 14;
	} else if (strcmp(curve_name, "secp128r1") == 0) {
		curve = NID_secp128r1;
		digest_len = 16;		
	} else if (strcmp(curve_name, "secp160r1") == 0) {
		curve = NID_secp160r1;
		digest_len = 20;		
	} else {
		return ERR_CURVE_UNKNOWN;
	}
	
	eckey = EC_KEY_new_by_curve_name(curve);
	if (eckey == NULL)
		return ERR_INIT_KEY;
	
	// set public key
	unsigned char *bin = NULL;
	size_t len = hex2bin(&bin, pubkey);
	if (len == 0)
		return ERR_PUBLIC_KEY_DECODING;
	const unsigned char *bin_copy = bin;
	eckey = o2i_ECPublicKey(&eckey, &bin_copy, len);
	OPENSSL_free(bin);
	
	// set private key
	len = hex2bin(&bin, privkey);
	if (len == 0)
		return ERR_PUBLIC_KEY_DECODING;
	bin_copy = bin;
	eckey = d2i_ECPrivateKey(&eckey, &bin_copy, len);
	OPENSSL_free(bin);
	
	// check keys
	if (!EC_KEY_check_key(eckey))
		return ERR_WRONG_KEYS;
	
	// calculate sha-1
	unsigned char digest[digest_len];
    el_compute_digest(name, digest, digest_len);

	// sign
	ECDSA_SIG *sig = ECDSA_do_sign(digest, digest_len, eckey);
	if (sig == NULL)
		return ERR_SIGNING;
	
	size_t rlen = BN_num_bytes(sig->r);
	size_t slen = BN_num_bytes(sig->s);
	size_t binlen = rlen + slen;
	bin = OPENSSL_malloc(binlen);
	bzero(bin, binlen);
	BN_bn2bin(sig->r, bin);
	BN_bn2bin(sig->s, bin + rlen); // join two values into bin
	ECDSA_SIG_free(sig);
	
	size_t b32len = el_base32_encode_buffer_size(binlen);
	char *base32 = OPENSSL_malloc(b32len);
	bzero(base32, b32len);

    el_base32_encode(bin, binlen, base32, b32len);
	printf("%s", base32);
	
	OPENSSL_free(bin);
	OPENSSL_free(base32);
	return 0;
}
Beispiel #28
0
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;
}
Beispiel #29
0
BOOL generate_SSH2_keysign(Key *keypair, char **sigptr, int *siglen, char *data, int datalen)
{
	buffer_t *msg = NULL;
	char *s;
	int ret;

	msg = buffer_init();
	if (msg == NULL) {
		// TODO: error check
		return FALSE;
	}

	switch (keypair->type) {
	case KEY_RSA: // RSA
	{
		const EVP_MD *evp_md = EVP_sha1();
		EVP_MD_CTX md;
		u_char digest[EVP_MAX_MD_SIZE], *sig;
		u_int slen, dlen, len;
		int ok, nid = NID_sha1;

		// ダイジェスト値の計算
		EVP_DigestInit(&md, evp_md);
		EVP_DigestUpdate(&md, data, datalen);
		EVP_DigestFinal(&md, digest, &dlen);

		slen = RSA_size(keypair->rsa);
		sig = malloc(slen);
		if (sig == NULL)
			goto error;

		// 電子署名を計算
		ok = RSA_sign(nid, digest, dlen, sig, &len, keypair->rsa);
		memset(digest, 'd', sizeof(digest));
		if (ok != 1) { // error
			free(sig);
			goto error;
		}
		// 署名のサイズがバッファより小さい場合、後ろへずらす。先頭はゼロで埋める。
		if (len < slen) {
			u_int diff = slen - len;
			memmove(sig + diff, sig, len);
			memset(sig, 0, diff);

		} else if (len > slen) {
			free(sig);
			goto error;

		} else {
			// do nothing

		}

		s = get_sshname_from_key(keypair);
		buffer_put_string(msg, s, strlen(s));
		buffer_append_length(msg, sig, slen);
		len = buffer_len(msg);

		// setting
		*siglen = len;
		*sigptr = malloc(len);
		if (*sigptr == NULL) {
			free(sig);
			goto error;
		}
		memcpy(*sigptr, buffer_ptr(msg), len);
		free(sig);
		
		break;
	}
	case KEY_DSA: // DSA
	{
		DSA_SIG *sig;
		const EVP_MD *evp_md = EVP_sha1();
		EVP_MD_CTX md;
		u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
		u_int rlen, slen, len, dlen;

		// ダイジェストの計算
		EVP_DigestInit(&md, evp_md);
		EVP_DigestUpdate(&md, data, datalen);
		EVP_DigestFinal(&md, digest, &dlen);

		// DSA電子署名を計算
		sig = DSA_do_sign(digest, dlen, keypair->dsa);
		memset(digest, 'd', sizeof(digest));
		if (sig == NULL) {
			goto error;
		}

		// BIGNUMからバイナリ値への変換
		rlen = BN_num_bytes(sig->r);
		slen = BN_num_bytes(sig->s);
		if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
			DSA_SIG_free(sig);
			goto error;
		}
		memset(sigblob, 0, SIGBLOB_LEN);
		BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
		BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
		DSA_SIG_free(sig);

		// setting
		s = get_sshname_from_key(keypair);
		buffer_put_string(msg, s, strlen(s));
		buffer_append_length(msg, sigblob, sizeof(sigblob));
		len = buffer_len(msg);

		// setting
		*siglen = len;
		*sigptr = malloc(len);
		if (*sigptr == NULL) {
			goto error;
		}
		memcpy(*sigptr, buffer_ptr(msg), len);

		break;
	}
	case KEY_ECDSA256: // ECDSA
	case KEY_ECDSA384:
	case KEY_ECDSA521:
	{
		ECDSA_SIG *sig;
		const EVP_MD *evp_md;
		EVP_MD_CTX md;
		u_char digest[EVP_MAX_MD_SIZE];
		u_int len, dlen, nid;
		buffer_t *buf2 = NULL;

		nid = keytype_to_hash_nid(keypair->type);
		if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
			goto error;
		}
		EVP_DigestInit(&md, evp_md);
		EVP_DigestUpdate(&md, data, datalen);
		EVP_DigestFinal(&md, digest, &dlen);

		sig = ECDSA_do_sign(digest, dlen, keypair->ecdsa);
		memset(digest, 'd', sizeof(digest));

		if (sig == NULL) {
			goto error;
		}

		buf2 = buffer_init();
		if (buf2 == NULL) {
			// TODO: error check
			goto error;
		}
		buffer_put_bignum2(buf2, sig->r);
		buffer_put_bignum2(buf2, sig->s);
		ECDSA_SIG_free(sig);

		s = get_sshname_from_key(keypair);
		buffer_put_string(msg, s, strlen(s));
		buffer_put_string(msg, buffer_ptr(buf2), buffer_len(buf2));
		buffer_free(buf2);
		len = buffer_len(msg);

		*siglen = len;
		*sigptr = malloc(len);
		if (*sigptr == NULL) {
			goto error;
		}
		memcpy(*sigptr, buffer_ptr(msg), len);

		break;
	}

	case KEY_ED25519:
		ret = ssh_ed25519_sign(keypair, sigptr, siglen, data, datalen);
		if (ret != 0) 
			goto error;
		break;

	default:
		buffer_free(msg);
		return FALSE;
		break;
	}

	buffer_free(msg);
	return TRUE;

error:
	buffer_free(msg);

	return FALSE;
}
Beispiel #30
0
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;
}