/*!
 * Acquires 16 Bytes IV from the iv-pool
 *
 * \param drvdata Driver private context
 * \param iv_out_dma The phys. IV out address
 * \param iv_out_size May be 8 or 16 bytes long
 * \param iv_seq IN/OUT array to the descriptors sequence
 * \param iv_seq_len IN/OUT pointer to the sequence length
 *
 * \return int Zero for success, negative value otherwise.
 */
int dx_ivgen_getiv(
	struct dx_drvdata *drvdata,
	dma_addr_t iv_out_dma,
	unsigned int iv_out_size,
	HwDesc_s iv_seq[],
	unsigned int *iv_seq_len)
{
	struct dx_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
	unsigned int idx = *iv_seq_len;

	if ((iv_out_size != SEP_AES_IV_SIZE) &&
	    (iv_out_size != CTR_RFC3686_IV_SIZE)) {
		return -EINVAL;
	}

	/* Acquire IV from pool */
	HW_DESC_INIT(&iv_seq[idx]);
	HW_DESC_SET_DIN_SRAM(&iv_seq[idx],
		ivgen_ctx->pool + ivgen_ctx->next_iv_ofs,
		iv_out_size);
	HW_DESC_SET_DOUT_DLLI(&iv_seq[idx], iv_out_dma,
		iv_out_size, AXI_ID, NS_BIT, 0);
	HW_DESC_SET_FLOW_MODE(&iv_seq[idx], BYPASS);
	idx++;

	/* Bypass operation is proceeded by crypto sequence, hence must
	*  assure bypass-write-transaction by a memory barrier */
	HW_DESC_INIT(&iv_seq[idx]);
	HW_DESC_SET_DIN_NO_DMA(&iv_seq[idx], 0, 0xfffff0);
	HW_DESC_SET_DOUT_NO_DMA(&iv_seq[idx], 0, 0, 1);
	idx++;

	*iv_seq_len = idx; /* update seq length */

	/* Update iv index */
	ivgen_ctx->next_iv_ofs += iv_out_size;

	if ((DX_IVPOOL_SIZE - ivgen_ctx->next_iv_ofs) < SEP_AES_IV_SIZE) {
		DX_LOG_DEBUG("Pool exhausted, regenerating iv-pool\n");
		/* pool is drained -regenerate it! */
		dx_ivgen_generate_pool(ivgen_ctx, iv_seq, iv_seq_len);
	}

	return 0;
}
示例#2
0
void LoadCipherKey(int qid, struct sep_ctx_cipher *pCtx)
{
	HwDesc_s desc;
	uint32_t keySize = ReadContextWord(&pCtx->key_size);
	XcbcMacRfcKeys_s *XcbcKeys = (XcbcMacRfcKeys_s*)pCtx->key;
	SepCipherPrivateContext_s *pAesPrivateCtx = (SepCipherPrivateContext_s *)pCtx->reserved;
	enum sep_crypto_direction encDecFlag = ReadContextWord(&pCtx->direction);

	HW_DESC_INIT(&desc);

	/* key size 24 bytes count as 32 bytes, make sure to zero wise upper 8 bytes */
	if (keySize == 24) {
		keySize	= SEP_AES_KEY_SIZE_MAX;
		ClearCtxField(&pCtx->key[24], SEP_AES_KEY_SIZE_MAX - 24);
	}

	HW_DESC_SET_CIPHER_MODE(&desc, ReadContextWord(&pCtx->mode));
	if (ReadContextWord(&pCtx->alg) == SEP_CRYPTO_ALG_AES) {
		if ((ReadContextWord(&pCtx->crypto_key_type) == DX_XOR_HDCP_KEY) &&
		    (ReadContextWord(&pCtx->direction) == SEP_CRYPTO_DIRECTION_DECRYPT)) {
			/* if the crypto operation is DECRYPT we still order the HW for ENCRYPT operation 
			when using HDCP key. The next decriptor which loads the HDCP XOR key will direct DECRYPT
			operation. */
			encDecFlag = SEP_CRYPTO_DIRECTION_ENCRYPT;
		}
		HW_DESC_SET_CIPHER_CONFIG0(&desc, ReadContextWord(&pAesPrivateCtx->isTunnelOp) ? ReadContextWord(&pAesPrivateCtx->tunnetDir) : encDecFlag);
		HW_DESC_SET_CIPHER_CONFIG1(&desc, ReadContextWord(&pAesPrivateCtx->isTunnelOp));
		switch (ReadContextWord(&pCtx->mode)) {
		case SEP_CIPHER_XCBC_MAC:
			HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)XcbcKeys->K1, SEP_AES_128_BIT_KEY_SIZE);
			HW_DESC_SET_KEY_SIZE_AES(&desc, SEP_AES_128_BIT_KEY_SIZE);
			if (ReadContextWord(&pCtx->crypto_key_type) == DX_XOR_HDCP_KEY) {
				HW_DESC_SET_AES_XOR_CRYPTO_KEY(&desc);
			}
			break;
		default:
			switch (ReadContextWord(&pCtx->crypto_key_type)) {
			case DX_ROOT_KEY:
				HW_DESC_SET_CIPHER_DO(&desc, ReadContextWord(&pCtx->crypto_key_type));
				break;
			case DX_SESSION_KEY:
				HW_DESC_SET_CIPHER_DO(&desc, SESSION_KEY); //value to be written to DO when session key is used
				break;
			case DX_XOR_HDCP_KEY:
				HW_DESC_SET_AES_XOR_CRYPTO_KEY(&desc);
				/*FALLTHROUGH*/
			case DX_USER_KEY:
			case DX_APPLET_KEY:
			default:
				HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)pCtx->key, keySize);
			}
			HW_DESC_SET_KEY_SIZE_AES(&desc, ReadContextWord(&pCtx->key_size));
		}

		if (ReadContextWord(&pAesPrivateCtx->engineCore) == SEP_AES_ENGINE2) {
			HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES2);
		} else {
			HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES);
		}
	} else {
		HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)pCtx->key, ReadContextWord(&pCtx->key_size));
		HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_DES);
		HW_DESC_SET_KEY_SIZE_DES(&desc, ReadContextWord(&pCtx->key_size));
		HW_DESC_SET_CIPHER_CONFIG0(&desc, encDecFlag);
	}

	HW_DESC_SET_SETUP_MODE(&desc, SETUP_LOAD_KEY0);
	AddHWDescSequence(qid, &desc);

	if ((ReadContextWord(&pCtx->alg) == SEP_CRYPTO_ALG_AES) &&
	    (ReadContextWord(&pCtx->crypto_key_type) == DX_XOR_HDCP_KEY)) {
		/* in HDCP, the user key being XORed with SEP_HDCP_CONST registers on the fly.
		   We reusing the descriptor and overwrite the necessary bits so DO NOT
		   clear the descriptor before. */
		HW_DESC_SET_DIN_NO_DMA(&desc, NO_DMA, 0);
		HW_DESC_SET_CIPHER_CONFIG0(&desc, ReadContextWord(&pCtx->direction)); /* user direction */
		HW_DESC_SET_CIPHER_DO(&desc, ReadContextWord(&pCtx->crypto_key_type));
		AddHWDescSequence(qid, &desc);
	}

	if (ReadContextWord(&pCtx->mode) == SEP_CIPHER_XTS) {
		HW_DESC_INIT(&desc);

		/* load XEX key */
		HW_DESC_SET_CIPHER_MODE(&desc, ReadContextWord(&pCtx->mode));
		HW_DESC_SET_CIPHER_CONFIG0(&desc, ReadContextWord(&pAesPrivateCtx->isTunnelOp) ? ReadContextWord(&pAesPrivateCtx->tunnetDir) : encDecFlag);
		HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)pCtx->xex_key, keySize);
		HW_DESC_SET_XEX_DATA_UNIT_SIZE(&desc, ReadContextWord(&pCtx->data_unit_size));
		HW_DESC_SET_CIPHER_CONFIG1(&desc, ReadContextWord(&pAesPrivateCtx->isTunnelOp));
		if (ReadContextWord(&pAesPrivateCtx->engineCore) == SEP_AES_ENGINE2) {
			HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES2);
		} else {
			HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES);
		}
		HW_DESC_SET_KEY_SIZE_AES(&desc, keySize);
		HW_DESC_SET_SETUP_MODE(&desc, SETUP_LOAD_XEX_KEY);
		AddHWDescSequence(qid, &desc);
	}

	if (ReadContextWord(&pCtx->mode) == SEP_CIPHER_XCBC_MAC) {

		/* load K2 key */
		/* NO init - reuse previous descriptor settings */
		HW_DESC_SET_STATE_DIN_PARAM(&desc,(uint32_t)XcbcKeys->K2, SEP_AES_128_BIT_KEY_SIZE);
		HW_DESC_SET_SETUP_MODE(&desc, SETUP_LOAD_STATE1);
		AddHWDescSequence(qid, &desc);

		/* load K3 key */
		/* NO init - reuse previous descriptor settings */
		HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)XcbcKeys->K3, SEP_AES_128_BIT_KEY_SIZE);
		HW_DESC_SET_SETUP_MODE(&desc, SETUP_LOAD_STATE2);
		AddHWDescSequence(qid, &desc);
	}
}