Skip to content

Commit

Permalink
crypto: caam - Detect hardware features during algorithm registration
Browse files Browse the repository at this point in the history
Register only algorithms supported by CAAM hardware, using the CHA
version and instantiation registers to identify hardware capabilities.

Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com>
Tested-by: Horia Geantă <horia.geanta@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Victoria Milhoan authored and Herbert Xu committed Aug 10, 2015
1 parent 350cdfe commit bf83490
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 18 deletions.
68 changes: 62 additions & 6 deletions drivers/crypto/caam/caamalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4371,8 +4371,10 @@ static int __init caam_algapi_init(void)
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
void *priv;
struct caam_drv_private *priv;
int i = 0, err = 0;
u32 cha_vid, cha_inst, des_inst, aes_inst, md_inst;
unsigned int md_limit = SHA512_DIGEST_SIZE;
bool registered = false;

dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
Expand Down Expand Up @@ -4402,16 +4404,39 @@ static int __init caam_algapi_init(void)

INIT_LIST_HEAD(&alg_list);

/* register crypto algorithms the device supports */
/*
* Register crypto algorithms the device supports.
* First, detect presence and attributes of DES, AES, and MD blocks.
*/
cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> CHA_ID_LS_DES_SHIFT;
aes_inst = (cha_inst & CHA_ID_LS_AES_MASK) >> CHA_ID_LS_AES_SHIFT;
md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;

/* If MD is present, limit digest size based on LP256 */
if (md_inst && ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256))
md_limit = SHA256_DIGEST_SIZE;

for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
/* TODO: check if h/w supports alg */
struct caam_crypto_alg *t_alg;
struct caam_alg_template *alg = driver_algs + i;
u32 alg_sel = alg->class1_alg_type & OP_ALG_ALGSEL_MASK;

/* Skip DES algorithms if not supported by device */
if (!des_inst &&
((alg_sel == OP_ALG_ALGSEL_3DES) ||
(alg_sel == OP_ALG_ALGSEL_DES)))
continue;

/* Skip AES algorithms if not supported by device */
if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
continue;

t_alg = caam_alg_alloc(&driver_algs[i]);
t_alg = caam_alg_alloc(alg);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
pr_warn("%s alg allocation failed\n",
driver_algs[i].driver_name);
pr_warn("%s alg allocation failed\n", alg->driver_name);
continue;
}

Expand All @@ -4429,6 +4454,37 @@ static int __init caam_algapi_init(void)

for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) {
struct caam_aead_alg *t_alg = driver_aeads + i;
u32 c1_alg_sel = t_alg->caam.class1_alg_type &
OP_ALG_ALGSEL_MASK;
u32 c2_alg_sel = t_alg->caam.class2_alg_type &
OP_ALG_ALGSEL_MASK;
u32 alg_aai = t_alg->caam.class1_alg_type & OP_ALG_AAI_MASK;

/* Skip DES algorithms if not supported by device */
if (!des_inst &&
((c1_alg_sel == OP_ALG_ALGSEL_3DES) ||
(c1_alg_sel == OP_ALG_ALGSEL_DES)))
continue;

/* Skip AES algorithms if not supported by device */
if (!aes_inst && (c1_alg_sel == OP_ALG_ALGSEL_AES))
continue;

/*
* Check support for AES algorithms not available
* on LP devices.
*/
if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP)
if (alg_aai == OP_ALG_AAI_GCM)
continue;

/*
* Skip algorithms requiring message digests
* if MD or MD size is not supported by device.
*/
if (c2_alg_sel &&
(!md_inst || (t_alg->aead.maxauthsize > md_limit)))
continue;

caam_aead_alg_init(t_alg);

Expand Down
38 changes: 30 additions & 8 deletions drivers/crypto/caam/caamhash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1883,8 +1883,10 @@ static int __init caam_algapi_hash_init(void)
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
void *priv;
int i = 0, err = 0;
struct caam_drv_private *priv;
unsigned int md_limit = SHA512_DIGEST_SIZE;
u32 cha_inst, cha_vid;

dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
if (!dev_node) {
Expand All @@ -1910,19 +1912,40 @@ static int __init caam_algapi_hash_init(void)
if (!priv)
return -ENODEV;

/*
* Register crypto algorithms the device supports. First, identify
* presence and attributes of MD block.
*/
cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);

/*
* Skip registration of any hashing algorithms if MD block
* is not present.
*/
if (!((cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT))
return -ENODEV;

/* Limit digest size based on LP256 */
if ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)
md_limit = SHA256_DIGEST_SIZE;

INIT_LIST_HEAD(&hash_list);

/* register crypto algorithms the device supports */
for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
/* TODO: check if h/w supports alg */
struct caam_hash_alg *t_alg;
struct caam_hash_template *alg = driver_hash + i;

/* If MD size is not supported by device, skip registration */
if (alg->template_ahash.halg.digestsize > md_limit)
continue;

/* register hmac version */
t_alg = caam_hash_alloc(&driver_hash[i], true);
t_alg = caam_hash_alloc(alg, true);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
pr_warn("%s alg allocation failed\n",
driver_hash[i].driver_name);
pr_warn("%s alg allocation failed\n", alg->driver_name);
continue;
}

Expand All @@ -1935,11 +1958,10 @@ static int __init caam_algapi_hash_init(void)
list_add_tail(&t_alg->entry, &hash_list);

/* register unkeyed version */
t_alg = caam_hash_alloc(&driver_hash[i], false);
t_alg = caam_hash_alloc(alg, false);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
pr_warn("%s alg allocation failed\n",
driver_hash[i].driver_name);
pr_warn("%s alg allocation failed\n", alg->driver_name);
continue;
}

Expand Down
6 changes: 5 additions & 1 deletion drivers/crypto/caam/caamrng.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ static int __init caam_rng_init(void)
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
void *priv;
struct caam_drv_private *priv;
int err;

dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
Expand All @@ -342,6 +342,10 @@ static int __init caam_rng_init(void)
if (!priv)
return -ENODEV;

/* Check for an instantiated RNG before registration */
if (!(rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & CHA_ID_LS_RNG_MASK))
return -ENODEV;

dev = caam_jr_alloc();
if (IS_ERR(dev)) {
pr_err("Job Ring Device allocation for transform failed\n");
Expand Down
16 changes: 13 additions & 3 deletions drivers/crypto/caam/regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,28 @@ struct jr_outentry {
#define CHA_NUM_MS_DECONUM_SHIFT 24
#define CHA_NUM_MS_DECONUM_MASK (0xfull << CHA_NUM_MS_DECONUM_SHIFT)

/* CHA Version IDs */
/*
* CHA version IDs / instantiation bitfields
* Defined for use with the cha_id fields in perfmon, but the same shift/mask
* selectors can be used to pull out the number of instantiated blocks within
* cha_num fields in perfmon because the locations are the same.
*/
#define CHA_ID_LS_AES_SHIFT 0
#define CHA_ID_LS_AES_MASK (0xfull << CHA_ID_LS_AES_SHIFT)
#define CHA_ID_LS_AES_MASK (0xfull << CHA_ID_LS_AES_SHIFT)
#define CHA_ID_LS_AES_LP (0x3ull << CHA_ID_LS_AES_SHIFT)
#define CHA_ID_LS_AES_HP (0x4ull << CHA_ID_LS_AES_SHIFT)

#define CHA_ID_LS_DES_SHIFT 4
#define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT)
#define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT)

#define CHA_ID_LS_ARC4_SHIFT 8
#define CHA_ID_LS_ARC4_MASK (0xfull << CHA_ID_LS_ARC4_SHIFT)

#define CHA_ID_LS_MD_SHIFT 12
#define CHA_ID_LS_MD_MASK (0xfull << CHA_ID_LS_MD_SHIFT)
#define CHA_ID_LS_MD_LP256 (0x0ull << CHA_ID_LS_MD_SHIFT)
#define CHA_ID_LS_MD_LP512 (0x1ull << CHA_ID_LS_MD_SHIFT)
#define CHA_ID_LS_MD_HP (0x2ull << CHA_ID_LS_MD_SHIFT)

#define CHA_ID_LS_RNG_SHIFT 16
#define CHA_ID_LS_RNG_MASK (0xfull << CHA_ID_LS_RNG_SHIFT)
Expand Down

0 comments on commit bf83490

Please sign in to comment.