Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16609980 authored by Gilad Ben-Yossef's avatar Gilad Ben-Yossef Committed by Greg Kroah-Hartman
Browse files

staging: ccree: add FIPS support



Add FIPS mode support to CryptoCell driver

Signed-off-by: default avatarGilad Ben-Yossef <gilad@benyossef.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fe0a1951
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -24,6 +24,15 @@ config CRYPTO_DEV_CCREE
	  cryptographic operations on the system REE.
	  If unsure say Y.

config CCREE_FIPS_SUPPORT
	bool "Turn on CryptoCell 7XX REE FIPS mode support"
	depends on CRYPTO_DEV_CCREE
	default n
	help
	  Say 'Y' to enable support for FIPS compliant mode by the
	  CCREE driver.
	  If unsure say N.

config CCREE_DISABLE_COHERENT_DMA_OPS
	bool "Disable Coherent DMA operations for the CCREE driver"
	depends on CRYPTO_DEV_CCREE
+1 −0
Original line number Diff line number Diff line
obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o
ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o
ccree-$(CCREE_FIPS_SUPPORT) += ssi_fips.o ssi_fips_ll.o ssi_fips_ext.o ssi_fips_local.o
+6 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include "ssi_hash.h"
#include "ssi_sysfs.h"
#include "ssi_sram_mgr.h"
#include "ssi_fips_local.h"

#define template_aead	template_u.aead

@@ -153,6 +154,8 @@ static int ssi_aead_init(struct crypto_aead *tfm)
			container_of(alg, struct ssi_crypto_alg, aead_alg);
	SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx, crypto_tfm_alg_name(&(tfm->base)));

	CHECK_AND_RETURN_UPON_FIPS_ERROR();

	/* Initialize modes in instance */
	ctx->cipher_mode = ssi_alg->cipher_mode;
	ctx->flow_mode = ssi_alg->flow_mode;
@@ -572,6 +575,7 @@ ssi_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
	SSI_LOG_DEBUG("Setting key in context @%p for %s. key=%p keylen=%u\n",
		ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);

	CHECK_AND_RETURN_UPON_FIPS_ERROR();
	/* STAT_PHASE_0: Init and sanity checks */
	START_CYCLE_COUNT();

@@ -699,6 +703,7 @@ static int ssi_aead_setauthsize(
{
	struct ssi_aead_ctx *ctx = crypto_aead_ctx(authenc);
	
	CHECK_AND_RETURN_UPON_FIPS_ERROR();
	/* Unsupported auth. sizes */
	if ((authsize == 0) ||
	    (authsize >crypto_aead_maxauthsize(authenc))) {
@@ -2006,6 +2011,7 @@ static int ssi_aead_process(struct aead_request *req, enum drv_crypto_direction
	SSI_LOG_DEBUG("%s context=%p req=%p iv=%p src=%p src_ofs=%d dst=%p dst_ofs=%d cryptolen=%d\n",
		((direct==DRV_CRYPTO_DIRECTION_ENCRYPT)?"Encrypt":"Decrypt"), ctx, req, req->iv,
		sg_virt(req->src), req->src->offset, sg_virt(req->dst), req->dst->offset, req->cryptlen);
	CHECK_AND_RETURN_UPON_FIPS_ERROR();

	/* STAT_PHASE_0: Init and sanity checks */
	START_CYCLE_COUNT();
+52 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include "ssi_cipher.h"
#include "ssi_request_mgr.h"
#include "ssi_sysfs.h"
#include "ssi_fips_local.h"

#define MAX_ABLKCIPHER_SEQ_LEN 6

@@ -191,6 +192,7 @@ static int ssi_blkcipher_init(struct crypto_tfm *tfm)
	SSI_LOG_DEBUG("Initializing context @%p for %s\n", ctx_p, 
						crypto_tfm_alg_name(tfm));

	CHECK_AND_RETURN_UPON_FIPS_ERROR();
	ctx_p->cipher_mode = ssi_alg->cipher_mode;
	ctx_p->flow_mode = ssi_alg->flow_mode;
	ctx_p->drvdata = ssi_alg->drvdata;
@@ -269,6 +271,37 @@ static const u8 zero_buff[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
                               0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

/* The function verifies that tdes keys are not weak.*/
static int ssi_fips_verify_3des_keys(const u8 *key, unsigned int keylen)
{
#ifdef CCREE_FIPS_SUPPORT
        tdes_keys_t *tdes_key = (tdes_keys_t*)key;

	/* verify key1 != key2 and key3 != key2*/
        if (unlikely( (memcmp((u8*)tdes_key->key1, (u8*)tdes_key->key2, sizeof(tdes_key->key1)) == 0) || 
		      (memcmp((u8*)tdes_key->key3, (u8*)tdes_key->key2, sizeof(tdes_key->key3)) == 0) )) {
                return -ENOEXEC;
        }
#endif /* CCREE_FIPS_SUPPORT */

        return 0;
}

/* The function verifies that xts keys are not weak.*/
static int ssi_fips_verify_xts_keys(const u8 *key, unsigned int keylen)
{
#ifdef CCREE_FIPS_SUPPORT
        /* Weak key is define as key that its first half (128/256 lsb) equals its second half (128/256 msb) */
        int singleKeySize = keylen >> 1;

	if (unlikely(memcmp(key, &key[singleKeySize], singleKeySize) == 0)) {
		return -ENOEXEC;
	}
#endif /* CCREE_FIPS_SUPPORT */

        return 0;
}

static enum HwCryptoKey hw_key_to_cc_hw_key(int slot_num)
{
	switch (slot_num) {
@@ -298,6 +331,10 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
		ctx_p, crypto_tfm_alg_name(tfm), keylen);
	dump_byte_array("key", (uint8_t *)key, keylen);

	CHECK_AND_RETURN_UPON_FIPS_ERROR();

	SSI_LOG_DEBUG("ssi_blkcipher_setkey: after FIPS check");
	
	/* STAT_PHASE_0: Init and sanity checks */
	START_CYCLE_COUNT();

@@ -359,6 +396,18 @@ static int ssi_blkcipher_setkey(struct crypto_tfm *tfm,
			return -EINVAL;
		}
	}
	if ((ctx_p->cipher_mode == DRV_CIPHER_XTS) && 
	    ssi_fips_verify_xts_keys(key, keylen) != 0) {
		SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak XTS key");
		return -EINVAL;
	}
	if ((ctx_p->flow_mode == S_DIN_to_DES) && 
	    (keylen == DES3_EDE_KEY_SIZE) && 
	    ssi_fips_verify_3des_keys(key, keylen) != 0) {
		SSI_LOG_DEBUG("ssi_blkcipher_setkey: weak 3DES key");
		return -EINVAL;
	}


	END_CYCLE_COUNT(STAT_OP_TYPE_SETKEY, STAT_PHASE_0);

@@ -744,6 +793,7 @@ static int ssi_blkcipher_process(
		((direction==DRV_CRYPTO_DIRECTION_ENCRYPT)?"Encrypt":"Decrypt"),
		     areq, info, nbytes);

	CHECK_AND_RETURN_UPON_FIPS_ERROR();
	/* STAT_PHASE_0: Init and sanity checks */
	START_CYCLE_COUNT();
	
@@ -864,6 +914,8 @@ static void ssi_ablkcipher_complete(struct device *dev, void *ssi_req, void __io
	struct ssi_ablkcipher_ctx *ctx_p = crypto_ablkcipher_ctx(tfm);
	unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);

	CHECK_AND_RETURN_VOID_UPON_FIPS_ERROR();

	ssi_blkcipher_complete(dev, ctx_p, req_ctx, areq->dst, areq->src, areq->info, ivsize, areq, cc_base);
}

+18 −1
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#include "ssi_ivgen.h"
#include "ssi_sram_mgr.h"
#include "ssi_pm.h"
#include "ssi_fips_local.h"


#ifdef DX_DUMP_BYTES
@@ -142,7 +143,15 @@ static irqreturn_t cc_isr(int irq, void *dev_id)
		irr &= ~SSI_COMP_IRQ_MASK;
		complete_request(drvdata);
	}

#ifdef CC_SUPPORT_FIPS
	/* TEE FIPS interrupt */
	if (likely((irr & SSI_GPR0_IRQ_MASK) != 0)) {
		/* Mask interrupt - will be unmasked in Deferred service handler */
		CC_HAL_WRITE_REGISTER(CC_REG_OFFSET(HOST_RGF, HOST_IMR), imr | SSI_GPR0_IRQ_MASK);
		irr &= ~SSI_GPR0_IRQ_MASK;
		fips_handler(drvdata);
	}
#endif
	/* AXI error interrupt */
	if (unlikely((irr & SSI_AXI_ERR_IRQ_MASK) != 0)) {
		uint32_t axi_err;
@@ -351,6 +360,12 @@ static int init_cc_resources(struct platform_device *plat_dev)
		goto init_cc_res_err;
	}

	rc = ssi_fips_init(new_drvdata);
	if (unlikely(rc != 0)) {
		SSI_LOG_ERR("SSI_FIPS_INIT failed 0x%x\n", rc);
		goto init_cc_res_err;
	}

	rc = ssi_ivgen_init(new_drvdata);
	if (unlikely(rc != 0)) {
		SSI_LOG_ERR("ssi_ivgen_init failed\n");
@@ -391,6 +406,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
		ssi_buffer_mgr_fini(new_drvdata);
		request_mgr_fini(new_drvdata);
		ssi_sram_mgr_fini(new_drvdata);
		ssi_fips_fini(new_drvdata);
#ifdef ENABLE_CC_SYSFS
		ssi_sysfs_fini();
#endif
@@ -434,6 +450,7 @@ static void cleanup_cc_resources(struct platform_device *plat_dev)
	ssi_buffer_mgr_fini(drvdata);
	request_mgr_fini(drvdata);
	ssi_sram_mgr_fini(drvdata);
	ssi_fips_fini(drvdata);
#ifdef ENABLE_CC_SYSFS
	ssi_sysfs_fini();
#endif
Loading