1471 lines · 39.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ #include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <crypto/algapi.h>#include <crypto/internal/skcipher.h>#include <crypto/internal/des.h>#include <crypto/xts.h>#include <crypto/sm4.h>#include <crypto/scatterwalk.h> #include "cc_driver.h"#include "cc_lli_defs.h"#include "cc_buffer_mgr.h"#include "cc_cipher.h"#include "cc_request_mgr.h" #define MAX_SKCIPHER_SEQ_LEN 6 #define template_skcipher	template_u.skcipher struct cc_user_key_info {	u8 *key;	dma_addr_t key_dma_addr;}; struct cc_hw_key_info {	enum cc_hw_crypto_key key1_slot;	enum cc_hw_crypto_key key2_slot;}; struct cc_cpp_key_info {	u8 slot;	enum cc_cpp_alg alg;}; enum cc_key_type {	CC_UNPROTECTED_KEY,		/* User key */	CC_HW_PROTECTED_KEY,		/* HW (FDE) key */	CC_POLICY_PROTECTED_KEY,	/* CPP key */	CC_INVALID_PROTECTED_KEY	/* Invalid key */}; struct cc_cipher_ctx {	struct cc_drvdata *drvdata;	int keylen;	int cipher_mode;	int flow_mode;	unsigned int flags;	enum cc_key_type key_type;	struct cc_user_key_info user;	union {		struct cc_hw_key_info hw;		struct cc_cpp_key_info cpp;	};	struct crypto_shash *shash_tfm;	struct crypto_skcipher *fallback_tfm;	bool fallback_on;}; static void cc_cipher_complete(struct device *dev, void *cc_req, int err); static inline enum cc_key_type cc_key_type(struct crypto_tfm *tfm){	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 	return ctx_p->key_type;} static int validate_keys_sizes(struct cc_cipher_ctx *ctx_p, u32 size){	switch (ctx_p->flow_mode) {	case S_DIN_to_AES:		switch (size) {		case CC_AES_128_BIT_KEY_SIZE:		case CC_AES_192_BIT_KEY_SIZE:			if (ctx_p->cipher_mode != DRV_CIPHER_XTS)				return 0;			break;		case CC_AES_256_BIT_KEY_SIZE:			return 0;		case (CC_AES_192_BIT_KEY_SIZE * 2):		case (CC_AES_256_BIT_KEY_SIZE * 2):			if (ctx_p->cipher_mode == DRV_CIPHER_XTS ||			    ctx_p->cipher_mode == DRV_CIPHER_ESSIV)				return 0;			break;		default:			break;		}		break;	case S_DIN_to_DES:		if (size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE)			return 0;		break;	case S_DIN_to_SM4:		if (size == SM4_KEY_SIZE)			return 0;		break;	default:		break;	}	return -EINVAL;} static int validate_data_size(struct cc_cipher_ctx *ctx_p,			      unsigned int size){	switch (ctx_p->flow_mode) {	case S_DIN_to_AES:		switch (ctx_p->cipher_mode) {		case DRV_CIPHER_XTS:		case DRV_CIPHER_CBC_CTS:			if (size >= AES_BLOCK_SIZE)				return 0;			break;		case DRV_CIPHER_OFB:		case DRV_CIPHER_CTR:				return 0;		case DRV_CIPHER_ECB:		case DRV_CIPHER_CBC:		case DRV_CIPHER_ESSIV:			if (IS_ALIGNED(size, AES_BLOCK_SIZE))				return 0;			break;		default:			break;		}		break;	case S_DIN_to_DES:		if (IS_ALIGNED(size, DES_BLOCK_SIZE))			return 0;		break;	case S_DIN_to_SM4:		switch (ctx_p->cipher_mode) {		case DRV_CIPHER_CTR:			return 0;		case DRV_CIPHER_ECB:		case DRV_CIPHER_CBC:			if (IS_ALIGNED(size, SM4_BLOCK_SIZE))				return 0;			break;		default:			break;		}		break;	default:		break;	}	return -EINVAL;} static int cc_cipher_init(struct crypto_tfm *tfm){	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);	struct cc_crypto_alg *cc_alg =			container_of(tfm->__crt_alg, struct cc_crypto_alg,				     skcipher_alg.base);	struct device *dev = drvdata_to_dev(cc_alg->drvdata);	unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize;	unsigned int fallback_req_size = 0; 	dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p,		crypto_tfm_alg_name(tfm)); 	ctx_p->cipher_mode = cc_alg->cipher_mode;	ctx_p->flow_mode = cc_alg->flow_mode;	ctx_p->drvdata = cc_alg->drvdata; 	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {		const char *name = crypto_tfm_alg_name(tfm); 		/* Alloc hash tfm for essiv */		ctx_p->shash_tfm = crypto_alloc_shash("sha256", 0, 0);		if (IS_ERR(ctx_p->shash_tfm)) {			dev_err(dev, "Error allocating hash tfm for ESSIV.\n");			return PTR_ERR(ctx_p->shash_tfm);		}		max_key_buf_size <<= 1; 		/* Alloc fallback tfm or essiv when key size != 256 bit */		ctx_p->fallback_tfm =			crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC); 		if (IS_ERR(ctx_p->fallback_tfm)) {			/* Note we're still allowing registration with no fallback since it's			 * better to have most modes supported than none at all.			 */			dev_warn(dev, "Error allocating fallback algo %s. Some modes may be available.\n",			       name);			ctx_p->fallback_tfm = NULL;		} else {			fallback_req_size = crypto_skcipher_reqsize(ctx_p->fallback_tfm);		}	} 	crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm),				    sizeof(struct cipher_req_ctx) + fallback_req_size); 	/* Allocate key buffer, cache line aligned */	ctx_p->user.key = kzalloc(max_key_buf_size, GFP_KERNEL);	if (!ctx_p->user.key)		goto free_fallback; 	dev_dbg(dev, "Allocated key buffer in context. key=@%p\n",		ctx_p->user.key); 	/* Map key buffer */	ctx_p->user.key_dma_addr = dma_map_single(dev, ctx_p->user.key,						  max_key_buf_size,						  DMA_TO_DEVICE);	if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) {		dev_err(dev, "Mapping Key %u B at va=%p for DMA failed\n",			max_key_buf_size, ctx_p->user.key);		goto free_key;	}	dev_dbg(dev, "Mapped key %u B at va=%p to dma=%pad\n",		max_key_buf_size, ctx_p->user.key, &ctx_p->user.key_dma_addr); 	return 0; free_key:	kfree(ctx_p->user.key);free_fallback:	crypto_free_skcipher(ctx_p->fallback_tfm);	crypto_free_shash(ctx_p->shash_tfm); 	return -ENOMEM;} static void cc_cipher_exit(struct crypto_tfm *tfm){	struct crypto_alg *alg = tfm->__crt_alg;	struct cc_crypto_alg *cc_alg =			container_of(alg, struct cc_crypto_alg,				     skcipher_alg.base);	unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize;	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);	struct device *dev = drvdata_to_dev(ctx_p->drvdata); 	dev_dbg(dev, "Clearing context @%p for %s\n",		crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm)); 	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {		/* Free hash tfm for essiv */		crypto_free_shash(ctx_p->shash_tfm);		ctx_p->shash_tfm = NULL;		crypto_free_skcipher(ctx_p->fallback_tfm);		ctx_p->fallback_tfm = NULL;	} 	/* Unmap key buffer */	dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size,			 DMA_TO_DEVICE);	dev_dbg(dev, "Unmapped key buffer key_dma_addr=%pad\n",		&ctx_p->user.key_dma_addr); 	/* Free key buffer in context */	dev_dbg(dev, "Free key buffer in context. key=@%p\n", ctx_p->user.key);	kfree_sensitive(ctx_p->user.key);} static enum cc_hw_crypto_key cc_slot_to_hw_key(u8 slot_num){	switch (slot_num) {	case 0:		return KFDE0_KEY;	case 1:		return KFDE1_KEY;	case 2:		return KFDE2_KEY;	case 3:		return KFDE3_KEY;	}	return END_OF_KEYS;} static u8 cc_slot_to_cpp_key(u8 slot_num){	return (slot_num - CC_FIRST_CPP_KEY_SLOT);} static inline enum cc_key_type cc_slot_to_key_type(u8 slot_num){	if (slot_num >= CC_FIRST_HW_KEY_SLOT && slot_num <= CC_LAST_HW_KEY_SLOT)		return CC_HW_PROTECTED_KEY;	else if (slot_num >=  CC_FIRST_CPP_KEY_SLOT &&		 slot_num <=  CC_LAST_CPP_KEY_SLOT)		return CC_POLICY_PROTECTED_KEY;	else		return CC_INVALID_PROTECTED_KEY;} static int cc_cipher_sethkey(struct crypto_skcipher *sktfm, const u8 *key,			     unsigned int keylen){	struct crypto_tfm *tfm = crypto_skcipher_tfm(sktfm);	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);	struct device *dev = drvdata_to_dev(ctx_p->drvdata);	struct cc_hkey_info hki; 	dev_dbg(dev, "Setting HW key in context @%p for %s. keylen=%u\n",		ctx_p, crypto_tfm_alg_name(tfm), keylen);	dump_byte_array("key", key, keylen); 	/* STAT_PHASE_0: Init and sanity checks */ 	/* This check the size of the protected key token */	if (keylen != sizeof(hki)) {		dev_err(dev, "Unsupported protected key size %d.\n", keylen);		return -EINVAL;	} 	memcpy(&hki, key, keylen); 	/* The real key len for crypto op is the size of the HW key	 * referenced by the HW key slot, not the hardware key token	 */	keylen = hki.keylen; 	if (validate_keys_sizes(ctx_p, keylen)) {		dev_dbg(dev, "Unsupported key size %d.\n", keylen);		return -EINVAL;	} 	ctx_p->keylen = keylen;	ctx_p->fallback_on = false; 	switch (cc_slot_to_key_type(hki.hw_key1)) {	case CC_HW_PROTECTED_KEY:		if (ctx_p->flow_mode == S_DIN_to_SM4) {			dev_err(dev, "Only AES HW protected keys are supported\n");			return -EINVAL;		} 		ctx_p->hw.key1_slot = cc_slot_to_hw_key(hki.hw_key1);		if (ctx_p->hw.key1_slot == END_OF_KEYS) {			dev_err(dev, "Unsupported hw key1 number (%d)\n",				hki.hw_key1);			return -EINVAL;		} 		if (ctx_p->cipher_mode == DRV_CIPHER_XTS ||		    ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {			if (hki.hw_key1 == hki.hw_key2) {				dev_err(dev, "Illegal hw key numbers (%d,%d)\n",					hki.hw_key1, hki.hw_key2);				return -EINVAL;			} 			ctx_p->hw.key2_slot = cc_slot_to_hw_key(hki.hw_key2);			if (ctx_p->hw.key2_slot == END_OF_KEYS) {				dev_err(dev, "Unsupported hw key2 number (%d)\n",					hki.hw_key2);				return -EINVAL;			}		} 		ctx_p->key_type = CC_HW_PROTECTED_KEY;		dev_dbg(dev, "HW protected key  %d/%d set\n.",			ctx_p->hw.key1_slot, ctx_p->hw.key2_slot);		break; 	case CC_POLICY_PROTECTED_KEY:		if (ctx_p->drvdata->hw_rev < CC_HW_REV_713) {			dev_err(dev, "CPP keys not supported in this hardware revision.\n");			return -EINVAL;		} 		if (ctx_p->cipher_mode != DRV_CIPHER_CBC &&		    ctx_p->cipher_mode != DRV_CIPHER_CTR) {			dev_err(dev, "CPP keys only supported in CBC or CTR modes.\n");			return -EINVAL;		} 		ctx_p->cpp.slot = cc_slot_to_cpp_key(hki.hw_key1);		if (ctx_p->flow_mode == S_DIN_to_AES)			ctx_p->cpp.alg = CC_CPP_AES;		else /* Must be SM4 since due to sethkey registration */			ctx_p->cpp.alg = CC_CPP_SM4;		ctx_p->key_type = CC_POLICY_PROTECTED_KEY;		dev_dbg(dev, "policy protected key alg: %d slot: %d.\n",			ctx_p->cpp.alg, ctx_p->cpp.slot);		break; 	default:		dev_err(dev, "Unsupported protected key (%d)\n", hki.hw_key1);		return -EINVAL;	} 	return 0;} static int cc_cipher_setkey(struct crypto_skcipher *sktfm, const u8 *key,			    unsigned int keylen){	struct crypto_tfm *tfm = crypto_skcipher_tfm(sktfm);	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);	struct device *dev = drvdata_to_dev(ctx_p->drvdata);	struct cc_crypto_alg *cc_alg =			container_of(tfm->__crt_alg, struct cc_crypto_alg,				     skcipher_alg.base);	unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize; 	dev_dbg(dev, "Setting key in context @%p for %s. keylen=%u\n",		ctx_p, crypto_tfm_alg_name(tfm), keylen);	dump_byte_array("key", key, keylen); 	/* STAT_PHASE_0: Init and sanity checks */ 	if (validate_keys_sizes(ctx_p, keylen)) {		dev_dbg(dev, "Invalid key size %d.\n", keylen);		return -EINVAL;	} 	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 		/* We only support 256 bit ESSIV-CBC-AES keys */		if (keylen != AES_KEYSIZE_256)  {			unsigned int flags = crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_MASK; 			if (likely(ctx_p->fallback_tfm)) {				ctx_p->fallback_on = true;				crypto_skcipher_clear_flags(ctx_p->fallback_tfm,							    CRYPTO_TFM_REQ_MASK);				crypto_skcipher_clear_flags(ctx_p->fallback_tfm, flags);				return crypto_skcipher_setkey(ctx_p->fallback_tfm, key, keylen);			} 			dev_dbg(dev, "Unsupported key size %d and no fallback.\n", keylen);			return -EINVAL;		} 		/* Internal ESSIV key buffer is double sized */		max_key_buf_size <<= 1;	} 	ctx_p->fallback_on = false;	ctx_p->key_type = CC_UNPROTECTED_KEY; 	/*	 * Verify DES weak keys	 * Note that we're dropping the expanded key since the	 * HW does the expansion on its own.	 */	if (ctx_p->flow_mode == S_DIN_to_DES) {		if ((keylen == DES3_EDE_KEY_SIZE &&		     verify_skcipher_des3_key(sktfm, key)) ||		    verify_skcipher_des_key(sktfm, key)) {			dev_dbg(dev, "weak DES key");			return -EINVAL;		}	} 	if (ctx_p->cipher_mode == DRV_CIPHER_XTS &&	    xts_verify_key(sktfm, key, keylen)) {		dev_dbg(dev, "weak XTS key");		return -EINVAL;	} 	/* STAT_PHASE_1: Copy key to ctx */	dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr,				max_key_buf_size, DMA_TO_DEVICE); 	memcpy(ctx_p->user.key, key, keylen); 	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {		/* sha256 for key2 - use sw implementation */		int err; 		err = crypto_shash_tfm_digest(ctx_p->shash_tfm,					      ctx_p->user.key, keylen,					      ctx_p->user.key + keylen);		if (err) {			dev_err(dev, "Failed to hash ESSIV key.\n");			return err;		} 		keylen <<= 1;	}	dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr,				   max_key_buf_size, DMA_TO_DEVICE);	ctx_p->keylen = keylen; 	dev_dbg(dev, "return safely");	return 0;} static int cc_out_setup_mode(struct cc_cipher_ctx *ctx_p){	switch (ctx_p->flow_mode) {	case S_DIN_to_AES:		return S_AES_to_DOUT;	case S_DIN_to_DES:		return S_DES_to_DOUT;	case S_DIN_to_SM4:		return S_SM4_to_DOUT;	default:

Lines 1–500 of 1471.