示例#1
0
/**
 * ECDH key derivation method (replaces ossl_ecdh_compute_key)
 * Implementation for OpenSSL 1.1.0-pre4 and later
 *
 * @param  out        derived key
 * @param  outlen     derived key length
 * @param  peer_point public key point
 * @param  ecdh       private key
 * @return 1 on success or 0 on error
 */
static int pkcs11_ec_ckey(unsigned char **out, size_t *outlen,
		const EC_POINT *peer_point, const EC_KEY *ecdh)
{
	PKCS11_KEY *key;
	CK_ECDH1_DERIVE_PARAMS *parms;
	unsigned char *buf = NULL;
	size_t buflen;
	int rv;

	key = (PKCS11_KEY *)EC_KEY_get_ex_data(ecdh, ec_ex_index);
	if (key == NULL) /* The private key is not handled by PKCS#11 */
		return ossl_ecdh_compute_key(out, outlen, peer_point, ecdh);
	/* 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 0;
	rv = pkcs11_ecdh_derive(&buf, &buflen, CKM_ECDH1_DERIVE, parms, NULL, key);
	pkcs11_ecdh_params_free(parms);
	if (rv < 0)
		return 0;

	*out = buf;
	*outlen = buflen;
	return 1;
}
示例#2
0
文件: crypto.c 项目: mbrossard/pkcs11
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;
    }
}
示例#3
0
文件: p11_ec.c 项目: OpenSC/libp11
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
}
示例#4
0
文件: p11_ec.c 项目: bphinz/libp11
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;
}
示例#5
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;
}
示例#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;
}
示例#7
0
文件: p11_ec.c 项目: bphinz/libp11
/* Our version of the ossl_ecdh_compute_key replaced in the EC_KEY_METHOD */
static int pkcs11_ec_ckey(void *out,
		size_t outlen,
		const EC_POINT *ecpointpeer,
		const EC_KEY *ecdh,
		void *(*KDF) (const void *in,
			size_t inlen,
			void *out,
			size_t *outlen))
{
	int ret = -1;
	size_t buflen;
	unsigned char *buf = NULL;
	size_t peerbuflen;
	unsigned char *peerbuf = NULL;
	const EC_GROUP *ecgroup = NULL;
	const EC_POINT *ecpoint = NULL;
	CK_ECDH1_DERIVE_PARAMS ecdh_parms;
	PKCS11_KEY * key = NULL;

	key = (PKCS11_KEY *) EC_KEY_get_ex_data(ecdh, ec_key_ex_index);

	if (key == NULL) {
	    ret -1;
	    goto err;
	}

	/* both peer and ecdh use same group parameters */
	ecgroup = EC_KEY_get0_group(ecdh);
	buflen = (EC_GROUP_get_degree(ecgroup) + 7) / 8;

	peerbuflen = 2*buflen + 1;
	peerbuf = OPENSSL_malloc(peerbuflen);
	if (peerbuf == NULL) {
		ret = -1;
		goto err;
	}

	ecdh_parms.kdf = CKD_NULL;
	ecdh_parms.ulSharedDataLen = 0;
	ecdh_parms.pSharedData = NULL;
	ecdh_parms.ulPublicDataLen = peerbuflen;
	ret = EC_POINT_point2oct(ecgroup,
			ecpointpeer,
			POINT_CONVERSION_UNCOMPRESSED,
			peerbuf, peerbuflen,NULL);
	ecdh_parms.ulPublicDataLen = peerbuflen;
	ecdh_parms.pPublicData = peerbuf;


	ret = pkcs11_ecdh_derive_internal(&buf, &buflen, CKM_ECDH1_DERIVE,
		(const void *)&ecdh_parms, NULL, key);

	if (KDF != 0) {
		if (KDF(buf, buflen, out, &outlen) == NULL) {
			ret -1;
			goto err;
		}
		ret = outlen;
	} else {
		if (outlen > buflen)
		    outlen = buflen;
		memcpy(out, buf, outlen);
		ret = outlen;
	}
err:
	OPENSSL_free(buf);
	return (ret);
}