Exemplo n.º 1
1
int test_builtin(BIO *out)
{
    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;
    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;
    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 (!RAND_pseudo_bytes(digest, 20) ||
            !RAND_pseudo_bytes(wrong_digest, 20)) {
        BIO_printf(out, "ERROR: unable to get random data\n");
        goto builtin_err;
    }

    /*
     * create and verify a ecdsa signature with every availble curve (with )
     */
    BIO_printf(out, "\ntesting ECDSA_sign() and ECDSA_verify() "
               "with some internal curves:\n");

    /* get a list of all internal curves */
    crv_len = EC_get_builtin_curves(NULL, 0);

    curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);

    if (curves == NULL) {
        BIO_printf(out, "malloc error\n");
        goto builtin_err;
    }

    if (!EC_get_builtin_curves(curves, crv_len)) {
        BIO_printf(out, "unable to get internal curves\n");
        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)
            continue;
        /* create new ecdsa key (== EC_KEY) */
        if ((eckey = EC_KEY_new()) == NULL)
            goto builtin_err;
        group = EC_GROUP_new_by_curve_name(nid);
        if (group == NULL)
            goto builtin_err;
        if (EC_KEY_set_group(eckey, group) == 0)
            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;
        }
        BIO_printf(out, "%s: ", OBJ_nid2sn(nid));
        /* create key */
        if (!EC_KEY_generate_key(eckey)) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        /* create second key */
        if ((wrong_eckey = EC_KEY_new()) == NULL)
            goto builtin_err;
        group = EC_GROUP_new_by_curve_name(nid);
        if (group == NULL)
            goto builtin_err;
        if (EC_KEY_set_group(wrong_eckey, group) == 0)
            goto builtin_err;
        EC_GROUP_free(group);
        if (!EC_KEY_generate_key(wrong_eckey)) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }

        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* check key */
        if (!EC_KEY_check_key(eckey)) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* create signature */
        sig_len = ECDSA_size(eckey);
        if ((signature = OPENSSL_malloc(sig_len)) == NULL)
            goto builtin_err;
        if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* verify signature */
        if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* verify signature with the wrong key */
        if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* wrong digest */
        if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);
        /* wrong length */
        if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);

        /*
         * 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 ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }

        /* Store the two BIGNUMs in raw_buf. */
        r_len = BN_num_bytes(ecdsa_sig->r);
        s_len = BN_num_bytes(ecdsa_sig->s);
        bn_len = (degree + 7) / 8;
        if ((r_len > bn_len) || (s_len > bn_len)) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        buf_len = 2 * bn_len;
        if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL)
            goto builtin_err;
        /* Pad the bignums with leading zeroes. */
        memset(raw_buf, 0, buf_len);
        BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len);
        BN_bn2bin(ecdsa_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 ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
                (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
            goto builtin_err;

        sig_ptr2 = signature;
        sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
        if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        /*
         * Sanity check: undo the modification and verify signature.
         */
        raw_buf[offset] ^= dirt;
        if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) ||
                (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL))
            goto builtin_err;

        sig_ptr2 = signature;
        sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
        if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
            BIO_printf(out, " failed\n");
            goto builtin_err;
        }
        BIO_printf(out, ".");
        (void)BIO_flush(out);

        BIO_printf(out, " ok\n");
        /* cleanup */
        /* clean bogus errors */
        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;
        OPENSSL_free(raw_buf);
        raw_buf = NULL;
    }

    ret = 1;
builtin_err:
    if (eckey)
        EC_KEY_free(eckey);
    if (wrong_eckey)
        EC_KEY_free(wrong_eckey);
    if (ecdsa_sig)
        ECDSA_SIG_free(ecdsa_sig);
    if (signature)
        OPENSSL_free(signature);
    if (raw_buf)
        OPENSSL_free(raw_buf);
    if (curves)
        OPENSSL_free(curves);

    return ret;
}
Exemplo n.º 2
0
bool CKey::ReserealizeSignature(std::vector<unsigned char>& vchSig) {
    unsigned char *pos;

    if (vchSig.empty())
        return false;

    pos = &vchSig[0];
    ECDSA_SIG *sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&pos, vchSig.size());
    if (sig == NULL)
        return false;

    bool ret = false;
    int nSize = i2d_ECDSA_SIG(sig, NULL);
    if (nSize > 0) {
        vchSig.resize(nSize); // grow or shrink as needed

        pos = &vchSig[0];
        i2d_ECDSA_SIG(sig, &pos);

        ret = true;
    }

    ECDSA_SIG_free(sig);
    return ret;
}
Exemplo n.º 3
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;
	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);
}
Exemplo n.º 4
0
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
    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;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
{
    vchSig.clear();
    ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey);
    if (sig == NULL)
        return false;
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);
    const EC_GROUP *group = EC_KEY_get0_group(pkey);
    BIGNUM *order = BN_CTX_get(ctx);
    BIGNUM *halforder = BN_CTX_get(ctx);
    EC_GROUP_get_order(group, order, ctx);
    BN_rshift1(halforder, order);
    if (BN_cmp(sig->s, halforder) > 0) {
        // enforce low S values, by negating the value (modulo the order) if above order/2.
        BN_sub(sig->s, order, sig->s);
    }
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    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
    return true;
}
Exemplo n.º 7
0
int ECDSA_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char 
	*sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, 
	EC_KEY *eckey)
{
//	BIO *out;//Added for test
	
	ECDSA_SIG *s;

	//Added for test
//	out=BIO_new(BIO_s_file());
//	if (out == NULL) return 0;
//	BIO_set_fp(out,stdout,BIO_NOCLOSE);
	
	s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey);
	if (s == NULL)
	{
		*siglen=0;
		return 0;
	}

//	printf("--------%s(%d),*siglen=%d-------\n",__FUNCTION__,__LINE__,*siglen);//Added for test
//	BN_print(out, s->r);//Added for test
//	BN_print(out, s->s);//Added for test
	*siglen = i2d_ECDSA_SIG(s, &sig);
//	printf("\n--------%s(%d),*siglen=%d-------\n",__FUNCTION__,__LINE__,*siglen);//Added for test
	ECDSA_SIG_free(s);
	return 1;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
// 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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
Arquivo: sign.c Projeto: dnstap/knot
/*!
 * \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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
int main(int argc, char **argv)
{
    CK_ULONG          nslots;
    CK_SLOT_ID        *pslots = NULL;
    CK_FUNCTION_LIST  *funcs = NULL;
    CK_UTF8CHAR_PTR   opt_pin = NULL;
    CK_ULONG          opt_pin_len = 0;
    CK_RV             rc;
    CK_ULONG          opt_slot = -1;
    CK_SESSION_HANDLE h_session;
    char *opt_module = NULL, *opt_dir = NULL;
    /* struct sockaddr_un sockaddr; */
    int long_optind = 0;
    int fd, verbose = 0;
    key_id_t *rsa_keys, *ec_keys;
    CK_ULONG rsa_len = 0, ec_len = 0, i;

    init_crypto();

    while (1) {
        char c = getopt_long(argc, argv, "d:hp:s:m:v",
                             options, &long_optind);
        if (c == -1)
            break;
        switch (c) {
            case 'd':
                opt_dir = optarg;
                break;
            case 'p':
                opt_pin = (CK_UTF8CHAR_PTR) strdup(optarg);
                if(opt_pin) {
                    opt_pin_len = strlen(optarg);
                }
                break;
            case 's':
                opt_slot = (CK_SLOT_ID) atoi(optarg);
                break;
            case 'm':
                opt_module = optarg;
                break;
            case 'v':
                verbose = 1;
                break;
            case 'h':
            default:
                print_usage_and_die(app_name, options, option_help);
        }
    }

    rc = pkcs11_load_init(opt_module, opt_dir, stderr, &funcs);
    if (rc != CKR_OK) {
        return rc;
    }

    rc = pkcs11_get_slots(funcs, stderr, &pslots, &nslots);
    if (rc != CKR_OK) {
        return rc;
    }

    if(opt_slot == -1) {
        if(nslots < 1) {
            /* No slots */
            return -1;
        } else {
            opt_slot = pslots[0];
        }
    } else {
        /* Check selected slot is in pslots */
    }

    fprintf(stderr, "Slot: %ld\n", opt_slot);
    rc = pkcs11_login_session(funcs, stderr, opt_slot, &h_session,
                              CK_TRUE, CKU_USER, opt_pin, opt_pin_len);
    if (rc != CKR_OK) {
        show_error(stderr, "Login", rc);
        return rc;
    }
    
    load_keys(funcs, h_session, CKK_RSA, &rsa_keys, &rsa_len);
    load_keys(funcs, h_session, CKK_EC,  &ec_keys,  &ec_len);


    /* fd = nw_unix_server("pkcs11d.sock", &sockaddr, 0, 0, 0, 64); */
    /* close(fd); */
    fd = nw_tcp_server(1234, 0, 64);
    
    do {
        struct sockaddr address;
        socklen_t a_len = sizeof(address);
        int s = accept(fd, &address, &a_len);
        BIO *b = BIO_new_socket(s, BIO_NOCLOSE);
        BIO *buf = BIO_new(BIO_f_buffer());
        b = BIO_push(buf, b);
        char buffer[4096], sig[4096], keyid[KEY_ID_SIZE + 1];
        int l, slen = 0, plen = 0;
        CK_KEY_TYPE type;
        CK_ATTRIBUTE_TYPE operation;
        EVP_PKEY *pkey = NULL;

        l = BIO_gets(b, buffer, sizeof(buffer));
        if(l <= 0) {
            fprintf(stderr, "Error reading query line\n");
            goto end;
        }

        if(strncmp(buffer, "POST /sign/rsa/", 15) == 0) {
            memcpy(keyid, buffer + 15, KEY_ID_SIZE - 1);
            type = CKK_RSA;
            operation = CKA_SIGN;
        } else if(strncmp(buffer, "POST /decrypt/rsa/", 18) == 0) {
            memcpy(keyid, buffer + 18, KEY_ID_SIZE - 1);
            type = CKK_RSA;
            operation = CKA_DECRYPT;
        } else if(strncmp(buffer, "POST /sign/ec/", 14) == 0) {
            memcpy(keyid, buffer + 14, KEY_ID_SIZE - 1);
            type = CKK_EC;
            operation = CKA_SIGN;
        } else {
            goto end;
        }
        keyid[KEY_ID_SIZE] = '\0';

        l = BIO_gets(b, buffer, sizeof(buffer));
        if((l <= 0) || strncmp(buffer, "Content-Length: ", 16) != 0) {
            fprintf(stderr, "Invalid content length line = %s\n", buffer);
            goto end;
        }
        plen = atoi(buffer + 16);
        l = BIO_gets(b, buffer, sizeof(buffer));
        l = BIO_read(b, buffer, plen);
        if(l < plen) {
            fprintf(stderr, "Error reading payload\n");
            goto end;
        }


        if(type == CKK_RSA) {
            for(i = 0; (i < rsa_len) && (pkey == NULL); i++) {
                if(strncmp(rsa_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) {
                    pkey = rsa_keys[i].key;
                }
            }
        } else if(type == CKK_EC) {
            for(i = 0; (i < ec_len) && (pkey == NULL); i++) {
                if(strncmp(ec_keys[i].id, keyid, KEY_ID_SIZE - 1) == 0) {
                    pkey = ec_keys[i].key;
                }
            }
        }
        if(pkey == NULL) {
            fprintf(stderr, "Key not found\n");
            goto end;
        } else if(verbose) {
            fprintf(stderr, "Key '%s'found\n", keyid);
        }
        
        if(type == CKK_RSA && operation == CKA_SIGN) {
            if(verbose) {
                fprintf(stderr, "RSA signature operation requested\n");
            }
            l = RSA_private_encrypt(plen, (unsigned char *)buffer, (unsigned char *)sig,
                                    EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING);
        } else if(type == CKK_RSA && operation == CKA_DECRYPT) {
            if(verbose) {
                fprintf(stderr, "RSA decryption operation requested\n");
            }
            l = RSA_private_decrypt(plen, (unsigned char *)buffer, (unsigned char *)sig,
                                    EVP_PKEY_get1_RSA(pkey), RSA_PKCS1_PADDING);
        } else if (type == CKK_EC && operation == CKA_SIGN) {
            unsigned char *ptr = (unsigned char *)sig;
            ECDSA_SIG *s = ECDSA_do_sign((unsigned char *)buffer, plen, EVP_PKEY_get1_EC_KEY(pkey));
            l = i2d_ECDSA_SIG(s, &ptr);
            ECDSA_SIG_free(s);
        } else {
            if(verbose) {
                fprintf(stderr, "Invalid operation requested\n");
            }
            goto end;
        }

        slen = l;
        if(l <= 0) {
            if(verbose) {
                fprintf(stderr, "Error unsuccessful\n");
            }
            goto end;
        } else if(verbose) {
            fprintf(stderr, "Operation successful\n");
        }

        BIO_printf(b, "200 Ok\r\n");
        BIO_printf(b, "Content-Length: %d\r\n\r\n", slen);

        l = BIO_write(b, sig, slen);
        BIO_flush(b);

        i= 0;
        /*
        for(i = 0; i < rsa_len; i++) {
            BIO_write(b, rsa_keys[i].id, KEY_ID_SIZE);
            BIO_write(b, "\n", 1);
            PEM_write_bio_RSAPrivateKey(b, EVP_PKEY_get1_RSA(rsa_keys[i].key), NULL, NULL, 0, NULL, NULL);
        }
        for(i = 0; i < ec_len; i++) {
            BIO_write(b, ec_keys[i].id, KEY_ID_SIZE);
            BIO_write(b, "\n", 1);
            PEM_write_bio_ECPrivateKey(b, EVP_PKEY_get1_EC_KEY(ec_keys[i].key), NULL, NULL, 0, NULL, NULL);
        }
        */


    end:
        close(s);
        BIO_free(b);
    } while(1);

    close(fd);

    if(opt_pin) {
        funcs->C_CloseAllSessions(opt_slot);
        free(opt_pin);
    }

    rc = funcs->C_Finalize(NULL);
    if (rc != CKR_OK) {
        show_error(stderr, "C_Finalize", rc);
        return rc;
    }
    
    return rc;
}
Exemplo n.º 16
0
bool CKey::Verify(uint256 hash, const std::vector<unsigned char>& vchSig)
{
    if( fNewerOpenSSL )
    {
        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];

        Yassert(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 = (
                    1 == ECDSA_verify(
                                      0, 
                                      (unsigned char*)&hash, 
                                      sizeof(hash), 
                                      norm_der, 
                                      derlen, 
                                      pkey
                                     )
                  );
        OPENSSL_free(norm_der);
        if (false == ret)
            return false;
        return ret;
    }
    else    // older version of OpenSSL, so do the old code
    {
        if (vchSig.empty())
        {
            printf( "\n\aECDSA signature verify called with nul argument?\n\n" );
        }
        const int
            nECDSAgood = 1,
            nECDSAbad = 0,
            nECDSAerror = -1;
        int
            nReturn = ECDSA_verify(
                                   0, 
                                   (unsigned char*)&hash, 
                                   sizeof(hash), 
                                   &vchSig[0], 
                                   vchSig.size(), 
                                   pkey
                                  );
        switch( nReturn )
        {
            case nECDSAgood:
                return true;
            case nECDSAbad:
                //printf( "\n\aECDSA signature verify FAILED?\n\n" );
                //(void)MessageBeep( MB_ICONERROR );
                return false;
            case nECDSAerror:
                //printf( "\n\aECDSA signature verify ERRORED?\n\n" );
                //(void)MessageBeep( MB_ICONERROR );
                return false;
            default:
                return false;
        }
    }
}
Exemplo n.º 17
0
int signMessageWithPem(char *message, char *pem, char **signature) {

    unsigned int meslen = strlen(message);
    unsigned char *messagebytes = calloc(meslen, sizeof(unsigned char));
    int derSigLen = 0;
    int i = 0;
    memcpy(messagebytes, message, meslen);

    EC_KEY *key = NULL;
    BIO *in = NULL;
    unsigned char *buffer = NULL;

    char *sha256ofMsg = calloc(SHA256_HEX_STRING, sizeof(char));
    unsigned char *outBytesOfsha256ofMsg = calloc(SHA256_STRING, sizeof(unsigned char));

    digestOfBytes(messagebytes, &sha256ofMsg, "sha256", meslen);
    sha256ofMsg[64] = '\0';
    createDataWithHexString(sha256ofMsg, &outBytesOfsha256ofMsg);
    
    in = BIO_new(BIO_s_mem());
    BIO_puts(in, pem);
    key = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
    
    if(key == NULL) {
       return ERROR;
    } 
    while(derSigLen < 70 && i < 10) {
        i++;
        ECDSA_SIG *sig = ECDSA_do_sign((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, key);
        
        int verify = ECDSA_do_verify((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, sig, key);
        
        if(verify != 1) {
            return ERROR;
        }

        int buflen = ECDSA_size(key);
        buffer = OPENSSL_malloc(buflen);

        derSigLen = i2d_ECDSA_SIG(sig, &buffer);
    }
    if(i == 10)
        return ERROR;
    char *hexData = calloc(derSigLen, sizeof(char));
    memcpy(hexData, buffer-derSigLen, derSigLen);

    char *hexString = calloc(derSigLen*2+1, sizeof(char));

    toHexString(hexData, derSigLen, &hexString);
    hexString[derSigLen * 2] = '\0';
    
    memcpy(*signature, hexString, (derSigLen*2)+ 1);

    EC_KEY_free(key);
    BIO_free_all(in);
    
    free(messagebytes);
    free(sha256ofMsg);
    free(outBytesOfsha256ofMsg);
    free(hexData);
    free(hexString);

    return NOERROR;
}
Exemplo n.º 18
0
int test_builtin(BIO *out) {
  size_t n = 0;
  EC_KEY *eckey = NULL, *wrong_eckey = NULL;
  EC_GROUP *group;
  BIGNUM *order = NULL;
  ECDSA_SIG *ecdsa_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;
  unsigned int sig_len, r_len, s_len, bn_len, buf_len;
  int nid, ret = 0;

  /* fill digest values with some random data */
  if (!RAND_pseudo_bytes(digest, 20) || !RAND_pseudo_bytes(wrong_digest, 20)) {
    BIO_printf(out, "ERROR: unable to get random data\n");
    goto builtin_err;
  }

  order = BN_new();
  if (order == NULL) {
    goto builtin_err;
  }

  /* create and verify a ecdsa signature with every availble curve
   * (with ) */
  BIO_printf(out,
             "\ntesting ECDSA_sign() and ECDSA_verify() "
             "with some internal curves:\n");

  static const int kCurveNIDs[] = {NID_secp224r1, NID_X9_62_prime256v1,
                                   NID_secp384r1, NID_secp521r1, NID_undef};

  /* now create and verify a signature for every curve */
  for (n = 0; kCurveNIDs[n] != NID_undef; n++) {
    unsigned char dirt, offset;

    nid = kCurveNIDs[n];
    /* create new ecdsa key (== EC_KEY) */
    eckey = EC_KEY_new();
    if (eckey == NULL) {
      goto builtin_err;
    }
    group = EC_GROUP_new_by_curve_name(nid);
    if (group == NULL) {
      goto builtin_err;
    }
    if (!EC_KEY_set_group(eckey, group)) {
      goto builtin_err;
    }
    EC_GROUP_free(group);
    if (!EC_GROUP_get_order(EC_KEY_get0_group(eckey), order, NULL)) {
      goto builtin_err;
    }
    if (BN_num_bits(order) < 160) {
      /* Too small to test. */
      EC_KEY_free(eckey);
      eckey = NULL;
      continue;
    }

    BIO_printf(out, "%s: ", OBJ_nid2sn(nid));
    /* create key */
    if (!EC_KEY_generate_key(eckey)) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    /* create second key */
    wrong_eckey = EC_KEY_new();
    if (wrong_eckey == NULL) {
      goto builtin_err;
    }
    group = EC_GROUP_new_by_curve_name(nid);
    if (group == NULL) {
      goto builtin_err;
    }
    if (EC_KEY_set_group(wrong_eckey, group) == 0) {
      goto builtin_err;
    }
    EC_GROUP_free(group);
    if (!EC_KEY_generate_key(wrong_eckey)) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }

    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* check key */
    if (!EC_KEY_check_key(eckey)) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* create signature */
    sig_len = ECDSA_size(eckey);
    signature = OPENSSL_malloc(sig_len);
    if (signature == NULL) {
      goto builtin_err;
    }
    if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* verify signature */
    if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* verify signature with the wrong key */
    if (ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey) == 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* wrong digest */
    if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey) == 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);
    /* wrong length */
    if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey) == 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);

    /* 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;
    ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len);
    if (ecdsa_sig == NULL) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }

    /* Store the two BIGNUMs in raw_buf. */
    r_len = BN_num_bytes(ecdsa_sig->r);
    s_len = BN_num_bytes(ecdsa_sig->s);
    bn_len = BN_num_bytes(order);
    if (r_len > bn_len || s_len > bn_len) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    buf_len = 2 * bn_len;
    raw_buf = OPENSSL_malloc(2 * bn_len);
    if (raw_buf == NULL) {
      goto builtin_err;
    }
    /* Pad the bignums with leading zeroes. */
    if (!BN_bn2bin_padded(raw_buf, bn_len, ecdsa_sig->r) ||
        !BN_bn2bin_padded(raw_buf + bn_len, bn_len, ecdsa_sig->s)) {
      goto builtin_err;
    }

    /* 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 (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
        BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
      goto builtin_err;
    }

    sig_ptr2 = signature;
    sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
    if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    /* Sanity check: undo the modification and verify signature. */
    raw_buf[offset] ^= dirt;
    if (BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL ||
        BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL) {
      goto builtin_err;
    }

    sig_ptr2 = signature;
    sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2);
    if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) {
      BIO_printf(out, " failed\n");
      goto builtin_err;
    }
    BIO_printf(out, ".");
    (void)BIO_flush(out);

    BIO_printf(out, " ok\n");
    /* cleanup */
    /* clean bogus errors */
    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;
    OPENSSL_free(raw_buf);
    raw_buf = NULL;
  }

  ret = 1;
builtin_err:
  if (eckey) {
    EC_KEY_free(eckey);
  }
  if (order) {
    BN_free(order);
  }
  if (wrong_eckey) {
    EC_KEY_free(wrong_eckey);
  }
  if (ecdsa_sig) {
    ECDSA_SIG_free(ecdsa_sig);
  }
  if (signature) {
    OPENSSL_free(signature);
  }
  if (raw_buf) {
    OPENSSL_free(raw_buf);
  }

  return ret;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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);
}
/**
 *
 * \brief Generates a digest then sends the digest to the
 *        ATECCX08 chip to generate an ECDSA signature using
 *        private key from TLS_SLOT_AUTH_PRIV slot. The private
 *        key is always stays in the chip: OpenSSL (nor any
 *        other software) has no way to read it.
 *
 * \param[in] ctx - a pointer to the EVP_MD_CTX structure
 * \param[in] it - a pointer to the ASN1_ITEM structure
 * \param[in] asn - a void pointer to the parameter
 * \param[in] algor1 - a pointer to the X509_ALGOR structure
 * \param[in] algor2 - a pointer to the X509_ALGOR structure
 * \param[out] signature - a pointer to the ASN1_BIT_STRING
 *       structure to return the signature in the ASN.1 format
 * \return 1 for success
 */
int eccx08_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
                     X509_ALGOR *algor1, X509_ALGOR *algor2,
                     ASN1_BIT_STRING *signature)
{
    int rc = 0;
    int ret = 0;
    const EVP_MD *type;
    EVP_PKEY *pkey;
    uint8_t *buf_in = NULL, *buf_out = NULL;
    uint8_t *sig_in = NULL, *sig_out = NULL;
    size_t inl = 0, outl = 0, outll = 0;
    int signid, paramtype;
    uint8_t slotid = TLS_SLOT_AUTH_PRIV;
    ATCA_STATUS status = ATCA_GEN_FAIL;

    extern ECDSA_METHOD eccx08_ecdsa;

    type = EVP_MD_CTX_md(ctx);
    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

    if (!type || !pkey) {
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
        return 0;
    }

    if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
        if (!pkey->ameth ||
            !OBJ_find_sigid_by_algs(&signid,
                                    EVP_MD_nid(type),
                                    pkey->ameth->pkey_id)) {
            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
                    ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
            return 0;
        }
    } else signid = type->pkey_type;

    if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) paramtype = V_ASN1_NULL;
    else paramtype = V_ASN1_UNDEF;

    if (algor1) X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
    if (algor2) X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

    inl = ASN1_item_i2d(asn, &buf_in, it);
    outll = outl = EVP_PKEY_size(pkey);
    buf_out = OPENSSL_malloc((unsigned int)outl);
    if ((buf_in == NULL) || (buf_out == NULL)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
#ifdef USE_ECCX08
    eccx08_debug("eccx08_item_sign() - HW\n");

    ret = EVP_DigestUpdate(ctx, buf_in, inl);
    if (!ret) goto done;
    ret = EVP_DigestFinal(ctx, buf_out, (unsigned int *)&outl);
    if (!ret) goto done;
    sig_in = OPENSSL_malloc((unsigned int)outll);  // source of crash
    sig_out = sig_in;
    if (sig_in == NULL) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
        goto done;
    }
    ECDSA_SIG *ecdsasig;
    ecdsasig = eccx08_ecdsa.ecdsa_do_sign(buf_out, outl, NULL, NULL, pkey->pkey.ec);
    if (ecdsasig == NULL) goto done;
    outl = i2d_ECDSA_SIG(ecdsasig, &sig_in);
    if (ecdsasig->r) {
        BN_free(ecdsasig->r);
        ecdsasig->r = NULL;
    }
    if (ecdsasig->s) {
        BN_free(ecdsasig->s);
        ecdsasig->s = NULL;
    }
    ECDSA_SIG_free(ecdsasig);

#else // USE_ECCX08
    eccx08_debug("eccx08_item_sign() - SW\n");
    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
        outl = 0;
        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
        goto done;
    }
#endif // USE_ECCX08
    if (signature->data != NULL) {
        OPENSSL_free(signature->data);
    }
#ifdef USE_ECCX08
    signature->data = sig_out;
    sig_out = NULL;
#else
    signature->data = buf_out;
    buf_out = NULL;
#endif
    signature->length = outl;
    /* 
     * ASN1_item_sign_ctx() in a_sign.c comment (just copy it here): 
     * In the interests of compatibility, I'll make sure that the bit string
     * has a 'not-used bits' value of 0
     */
    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;

    rc = 1;
done:
    EVP_MD_CTX_cleanup(ctx);
    if (buf_in != NULL) {
        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
        OPENSSL_free(buf_in);
    }
    if (buf_out != NULL) {
        OPENSSL_cleanse((char *)buf_out, outll);
        OPENSSL_free(buf_out);
    }
    if (sig_out != NULL) {
        OPENSSL_cleanse((char *)sig_out, outll);
        OPENSSL_free(sig_out);
    }
    return (rc);
}
Exemplo n.º 22
0
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;
}