Beispiel #1
0
static long zcrypt_rng(char *buffer)
{
	struct zcrypt_card *zc, *pref_zc;
	struct zcrypt_queue *zq, *pref_zq;
	unsigned int weight, pref_weight;
	unsigned int func_code;
	struct ap_message ap_msg;
	unsigned int domain;
	int qid = 0, rc = -ENODEV;

	trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);

	rc = get_rng_fc(&ap_msg, &func_code, &domain);
	if (rc)
		goto out;

	pref_zc = NULL;
	pref_zq = NULL;
	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		/* Check for online CCA cards */
		if (!zc->online || !(zc->card->functions & 0x10000000))
			continue;
		/* get weight index of the card device	*/
		weight = zc->speed_rating[func_code];
		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
			continue;
		for_each_zcrypt_queue(zq, zc) {
			/* check if device is online and eligible */
			if (!zq->online || !zq->ops->rng)
				continue;
			if (zcrypt_queue_compare(zq, pref_zq,
						 weight, pref_weight))
				continue;
			pref_zc = zc;
			pref_zq = zq;
			pref_weight = weight;
		}
	}
	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

	if (!pref_zq)
		return -ENODEV;

	qid = pref_zq->queue->qid;
	rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg);

	spin_lock(&zcrypt_list_lock);
	zcrypt_drop_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

out:
	trace_s390_zcrypt_rep(buffer, func_code, rc,
			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
	return rc;
}
Beispiel #2
0
static void zcrypt_device_status_mask(struct zcrypt_device_matrix *matrix)
{
	struct zcrypt_card *zc;
	struct zcrypt_queue *zq;
	struct zcrypt_device_status *stat;

	memset(matrix, 0, sizeof(*matrix));
	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		for_each_zcrypt_queue(zq, zc) {
			stat = matrix->device;
			stat += AP_QID_CARD(zq->queue->qid) * MAX_ZDEV_DOMAINS;
			stat += AP_QID_QUEUE(zq->queue->qid);
			stat->hwtype = zc->card->ap_dev.device_type;
			stat->functions = zc->card->functions >> 26;
			stat->qid = zq->queue->qid;
			stat->online = zq->online ? 0x01 : 0x00;
		}
	}
Beispiel #3
0
static void zcrypt_device_status_mask(struct zcrypt_device_status *devstatus)
{
	struct zcrypt_card *zc;
	struct zcrypt_queue *zq;
	struct zcrypt_device_status *stat;
	int card, queue;

	memset(devstatus, 0, MAX_ZDEV_ENTRIES
	       * sizeof(struct zcrypt_device_status));

	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		for_each_zcrypt_queue(zq, zc) {
			card = AP_QID_CARD(zq->queue->qid);
			if (card >= MAX_ZDEV_CARDIDS)
				continue;
			queue = AP_QID_QUEUE(zq->queue->qid);
			stat = &devstatus[card * AP_DOMAINS + queue];
			stat->hwtype = zc->card->ap_dev.device_type;
			stat->functions = zc->card->functions >> 26;
			stat->qid = zq->queue->qid;
			stat->online = zq->online ? 0x01 : 0x00;
		}
	}
Beispiel #4
0
static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
{
	struct zcrypt_card *zc, *pref_zc;
	struct zcrypt_queue *zq, *pref_zq;
	struct ep11_target_dev *targets;
	unsigned short target_num;
	unsigned int weight, pref_weight;
	unsigned int func_code;
	struct ap_message ap_msg;
	int qid = 0, rc = -ENODEV;

	trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);

	target_num = (unsigned short) xcrb->targets_num;

	/* empty list indicates autoselect (all available targets) */
	targets = NULL;
	if (target_num != 0) {
		struct ep11_target_dev __user *uptr;

		targets = kcalloc(target_num, sizeof(*targets), GFP_KERNEL);
		if (!targets) {
			rc = -ENOMEM;
			goto out;
		}

		uptr = (struct ep11_target_dev __force __user *) xcrb->targets;
		if (copy_from_user(targets, uptr,
				   target_num * sizeof(*targets))) {
			rc = -EFAULT;
			goto out;
		}
	}

	rc = get_ep11cprb_fc(xcrb, &ap_msg, &func_code);
	if (rc)
		goto out_free;

	pref_zc = NULL;
	pref_zq = NULL;
	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		/* Check for online EP11 cards */
		if (!zc->online || !(zc->card->functions & 0x04000000))
			continue;
		/* Check for user selected EP11 card */
		if (targets &&
		    !is_desired_ep11_card(zc->card->id, target_num, targets))
			continue;
		/* get weight index of the card device	*/
		weight = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY];
		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
			continue;
		for_each_zcrypt_queue(zq, zc) {
			/* check if device is online and eligible */
			if (!zq->online ||
			    !zq->ops->send_ep11_cprb ||
			    (targets &&
			     !is_desired_ep11_queue(zq->queue->qid,
						    target_num, targets)))
				continue;
			if (zcrypt_queue_compare(zq, pref_zq,
						 weight, pref_weight))
				continue;
			pref_zc = zc;
			pref_zq = zq;
			pref_weight = weight;
		}
	}
	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

	if (!pref_zq) {
		rc = -ENODEV;
		goto out_free;
	}

	qid = pref_zq->queue->qid;
	rc = pref_zq->ops->send_ep11_cprb(pref_zq, xcrb, &ap_msg);

	spin_lock(&zcrypt_list_lock);
	zcrypt_drop_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

out_free:
	kfree(targets);
out:
	trace_s390_zcrypt_rep(xcrb, func_code, rc,
			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
	return rc;
}
Beispiel #5
0
static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
{
	struct zcrypt_card *zc, *pref_zc;
	struct zcrypt_queue *zq, *pref_zq;
	struct ap_message ap_msg;
	unsigned int weight, pref_weight;
	unsigned int func_code;
	unsigned short *domain;
	int qid = 0, rc = -ENODEV;

	trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB);

	rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain);
	if (rc)
		goto out;

	pref_zc = NULL;
	pref_zq = NULL;
	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		/* Check for online CCA cards */
		if (!zc->online || !(zc->card->functions & 0x10000000))
			continue;
		/* Check for user selected CCA card */
		if (xcRB->user_defined != AUTOSELECT &&
		    xcRB->user_defined != zc->card->id)
			continue;
		/* get weight index of the card device	*/
		weight = speed_idx_cca(func_code) * zc->speed_rating[SECKEY];
		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
			continue;
		for_each_zcrypt_queue(zq, zc) {
			/* check if device is online and eligible */
			if (!zq->online ||
			    !zq->ops->send_cprb ||
			    ((*domain != (unsigned short) AUTOSELECT) &&
			     (*domain != AP_QID_QUEUE(zq->queue->qid))))
				continue;
			if (zcrypt_queue_compare(zq, pref_zq,
						 weight, pref_weight))
				continue;
			pref_zc = zc;
			pref_zq = zq;
			pref_weight = weight;
		}
	}
	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

	if (!pref_zq) {
		rc = -ENODEV;
		goto out;
	}

	/* in case of auto select, provide the correct domain */
	qid = pref_zq->queue->qid;
	if (*domain == (unsigned short) AUTOSELECT)
		*domain = AP_QID_QUEUE(qid);

	rc = pref_zq->ops->send_cprb(pref_zq, xcRB, &ap_msg);

	spin_lock(&zcrypt_list_lock);
	zcrypt_drop_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

out:
	trace_s390_zcrypt_rep(xcRB, func_code, rc,
			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
	return rc;
}
Beispiel #6
0
static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
{
	struct zcrypt_card *zc, *pref_zc;
	struct zcrypt_queue *zq, *pref_zq;
	unsigned int weight, pref_weight;
	unsigned int func_code;
	int qid = 0, rc = -ENODEV;

	trace_s390_zcrypt_req(crt, TP_ICARSACRT);

	if (crt->outputdatalength < crt->inputdatalength) {
		rc = -EINVAL;
		goto out;
	}

	/*
	 * As long as outputdatalength is big enough, we can set the
	 * outputdatalength equal to the inputdatalength, since that is the
	 * number of bytes we will copy in any case
	 */
	crt->outputdatalength = crt->inputdatalength;

	rc = get_rsa_crt_fc(crt, &func_code);
	if (rc)
		goto out;

	pref_zc = NULL;
	pref_zq = NULL;
	spin_lock(&zcrypt_list_lock);
	for_each_zcrypt_card(zc) {
		/* Check for online accelarator and CCA cards */
		if (!zc->online || !(zc->card->functions & 0x18000000))
			continue;
		/* Check for size limits */
		if (zc->min_mod_size > crt->inputdatalength ||
		    zc->max_mod_size < crt->inputdatalength)
			continue;
		/* get weight index of the card device	*/
		weight = zc->speed_rating[func_code];
		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
			continue;
		for_each_zcrypt_queue(zq, zc) {
			/* check if device is online and eligible */
			if (!zq->online || !zq->ops->rsa_modexpo_crt)
				continue;
			if (zcrypt_queue_compare(zq, pref_zq,
						 weight, pref_weight))
				continue;
			pref_zc = zc;
			pref_zq = zq;
			pref_weight = weight;
		}
	}
	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

	if (!pref_zq) {
		rc = -ENODEV;
		goto out;
	}

	qid = pref_zq->queue->qid;
	rc = pref_zq->ops->rsa_modexpo_crt(pref_zq, crt);

	spin_lock(&zcrypt_list_lock);
	zcrypt_drop_queue(pref_zc, pref_zq, weight);
	spin_unlock(&zcrypt_list_lock);

out:
	trace_s390_zcrypt_rep(crt, func_code, rc,
			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
	return rc;
}