Ejemplo n.º 1
0
static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len,
                                    const BIGNUM *inv, const BIGNUM *rp,
                                    EC_KEY *ecdsa) {
    struct pkcs11_key_data *pkd = NULL;
	CK_MECHANISM mech = {
		CKM_ECDSA, NULL_PTR, 0
	};
	CK_ULONG tlen = 0;
	CK_RV rv;

#if OPENSSL_VERSION_NUMBER < 0x10100000L
    pkd = ECDSA_get_ex_data(ecdsa, pkcs11_ecdsa_key_idx);
#else
    pkd = EC_KEY_get_ex_data(ecdsa, pkcs11_ecdsa_key_idx);
#endif
    if((pkd != NULL) &&
       ((rv = pkd->funcs->C_SignInit(pkd->session, &mech, pkd->key)) == CKR_OK)) {
		CK_BYTE_PTR buf = NULL;
        ECDSA_SIG *rval;
        BIGNUM *r, *s;
        int nlen;
        
        /* Make a call to C_Sign to find out the size of the signature */
        rv = pkd->funcs->C_Sign(pkd->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen);
        if (rv != CKR_OK) {
            return NULL;
        }
        
        if ((buf = malloc(tlen)) == NULL) {
            return NULL;
        }
        
        rv = pkd->funcs->C_Sign(pkd->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen);
        if (rv != CKR_OK) {
            free(buf);
            return NULL;
        }
        
        if ((rval = ECDSA_SIG_new()) != NULL) {
            /* 
             * ECDSA signature is 2 large integers of same size returned
             * concatenated by PKCS#11, we separate them to create an
             * ECDSA_SIG for OpenSSL.
             */
            nlen = tlen / 2;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
            ECDSA_SIG_get0(&r, &s, rval);
#else
            r = rval->r;
            s = rval->s;
#endif
            BN_bin2bn(&buf[0], nlen, r);
            BN_bin2bn(&buf[nlen], nlen, s);
        }
        free(buf);
        return rval;
    } else {
        return NULL;
    }
}
Ejemplo n.º 2
0
PKCS11_KEY *pkcs11_get_ex_data_ec(const EC_KEY *ec)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
	return EC_KEY_get_ex_data(ec, ec_ex_index);
#else
	return ECDSA_get_ex_data((EC_KEY *)ec, ec_ex_index);
#endif
}
Ejemplo n.º 3
0
static ECDSA_SIG * pkcs11_ecdsa_do_sign(const unsigned char *dgst, int dlen,
			const BIGNUM *inv, const BIGNUM *r, EC_KEY * ec)
{

	unsigned char sigret[512]; /* HACK for now */
	ECDSA_SIG * sig = NULL;
	PKCS11_KEY * key = NULL;
	unsigned int siglen;
	int nLen = 48; /* HACK */
	int rv;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	key = (PKCS11_KEY *) EC_KEY_get_ex_data(ec, ec_key_ex_index);
#else
	key = (PKCS11_KEY *) ECDSA_get_ex_data(ec, ecdsa_ex_index);
#endif
	if (key == NULL)
		return NULL;

	siglen = sizeof(sigret);

	rv = PKCS11_ecdsa_sign(dgst, dlen, sigret, &siglen, key);
	nLen = siglen / 2;
	if (rv > 0) {
		sig = ECDSA_SIG_new();
		if (sig) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
		/*
		 * OpenSSL 1.1 does not have a way to allocate r and s 
		 * in ECDSA_SIG as it is now hidden. 
		 * Will us dummy ASN1 so r and s are allocated then
		 * use ECDSA_SIG_get0 to get access to r and s 
		 * can then update r annd s
		 */
			const unsigned char *a;
			unsigned char dasn1[8] =
				{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00};
			BIGNUM *r;
			BIGNUM *s;
			a = dasn1;
			d2i_ECDSA_SIG(&sig, &a, 8);
			ECDSA_SIG_get0(&r, &s, sig);
			BN_bin2bn(&sigret[0], nLen, r);
			BN_bin2bn(&sigret[nLen], nLen, s);
#else
			BN_bin2bn(&sigret[0], nLen, sig->r);
			BN_bin2bn(&sigret[nLen], nLen, sig->s);
#endif
		}
	}
	return sig;
}
Ejemplo n.º 4
0
/**
 * ECDSA signing method (replaces ossl_ecdsa_sign_sig)
 *
 *  @param  dgst     hash value to sign
 *  @param  dlen     length of the hash value
 *  @param  kinv     precomputed inverse k (from the sign_setup method)
 *  @param  rp       precomputed rp (from the sign_setup method)
 *  @param  ec       private EC signing key
 *  @return pointer to a ECDSA_SIG structure or NULL if an error occurred
 */
static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen,
		const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *ec)
{
	unsigned char sigret[512]; /* HACK for now */
	ECDSA_SIG *sig;
	PKCS11_KEY *key;
	unsigned int siglen;
	BIGNUM *r, *s, *order;

	(void)kinv; /* Precomputed values are not used for PKCS#11 */
	(void)rp; /* Precomputed values are not used for PKCS#11 */

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	key = (PKCS11_KEY *)EC_KEY_get_ex_data(ec, ec_ex_index);
#else
	key = (PKCS11_KEY *)ECDSA_get_ex_data(ec, ec_ex_index);
#endif
	if (key == NULL) {
		PKCS11err(PKCS11_F_PKCS11_EC_KEY_SIGN, PKCS11_ALIEN_KEY);
		return NULL;
	}
	/* TODO: Add an atfork check */

	/* Truncate digest if its byte size is longer than needed */
	order = BN_new();
	if (order) {
		const EC_GROUP *group = EC_KEY_get0_group(ec);
		if (group && EC_GROUP_get_order(group, order, NULL)) {
			int klen = BN_num_bits(order);
			if (klen < 8*dlen)
				dlen = (klen+7)/8;
		}
		BN_free(order);
	}

	siglen = sizeof sigret;
	if (pkcs11_ecdsa_sign(dgst, dlen, sigret, &siglen, key) <= 0)
		return NULL;

	sig = ECDSA_SIG_new();
	if (sig == NULL)
		return NULL;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	ECDSA_SIG_get0(&r, &s, sig);
#else
	r = sig->r;
	s = sig->s;
#endif
	BN_bin2bn(sigret, siglen/2, r);
	BN_bin2bn(sigret + siglen/2, siglen/2, s);
	return sig;
}
Ejemplo n.º 5
0
static
pkcs11h_certificate_t
__pkcs11h_openssl_ecdsa_get_pkcs11h_certificate (
	IN EC_KEY *ec
) {
	pkcs11h_openssl_session_t session = NULL;

	_PKCS11H_ASSERT (ec!=NULL);

	session = (pkcs11h_openssl_session_t)ECDSA_get_ex_data (ec, __openssl_methods.ecdsa_index);

	_PKCS11H_ASSERT (session!=NULL);
	_PKCS11H_ASSERT (session->certificate!=NULL);

	return session->certificate;
}
Ejemplo n.º 6
0
/**
 * ECDH key derivation method (replaces ossl_ecdh_compute_key)
 * Implementation for OpenSSL 1.1.0-pre3 and earlier
 *
 * @param  out        derived key
 * @param  outlen     derived key length
 * @param  peer_point public key point
 * @param  ecdh       private key
 * @param  KCF        key derivation function
 * @return the length of the derived key or -1 if an error occurred
 */
static int pkcs11_ec_ckey(void *out, size_t outlen,
		const EC_POINT *peer_point, const EC_KEY *ecdh,
		void *(*KDF)(const void *, size_t, void *, size_t *))
{
	PKCS11_KEY *key;
	CK_ECDH1_DERIVE_PARAMS *parms;
	unsigned char *buf = NULL;
	size_t buflen;
	int rv;

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
	key = (PKCS11_KEY *)EC_KEY_get_ex_data(ecdh, ec_ex_index);
#else
	key = (PKCS11_KEY *)ECDSA_get_ex_data((EC_KEY *)ecdh, ec_ex_index);
#endif
	if (key == NULL) /* The private key is not handled by PKCS#11 */
		return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh, KDF);
	/* TODO: Add an atfork check */

	/* both peer and ecdh use same group parameters */
	parms = pkcs11_ecdh_params_alloc(EC_KEY_get0_group(ecdh), peer_point);
	if (parms == NULL)
		return -1;
	rv = pkcs11_ecdh_derive(&buf, &buflen, CKM_ECDH1_DERIVE, parms, NULL, key);
	pkcs11_ecdh_params_free(parms);
	if (rv < 0)
		return -1;

	if (KDF) {
		if (KDF(buf, buflen, out, &outlen) == NULL) {
			OPENSSL_free(buf);
			return -1;
		}
	} else {
		if (outlen > buflen)
			outlen = buflen;
		memcpy(out, buf, outlen);
	}
	OPENSSL_free(buf);
	return outlen;
}