Skip to content

Commit bf83490

Browse files
Victoria Milhoanherbertx
authored andcommitted
crypto: caam - Detect hardware features during algorithm registration
Register only algorithms supported by CAAM hardware, using the CHA version and instantiation registers to identify hardware capabilities. Signed-off-by: Victoria Milhoan <[email protected]> Tested-by: Horia Geantă <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 350cdfe commit bf83490

File tree

4 files changed

+110
-18
lines changed

4 files changed

+110
-18
lines changed

drivers/crypto/caam/caamalg.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4371,8 +4371,10 @@ static int __init caam_algapi_init(void)
43714371
struct device_node *dev_node;
43724372
struct platform_device *pdev;
43734373
struct device *ctrldev;
4374-
void *priv;
4374+
struct caam_drv_private *priv;
43754375
int i = 0, err = 0;
4376+
u32 cha_vid, cha_inst, des_inst, aes_inst, md_inst;
4377+
unsigned int md_limit = SHA512_DIGEST_SIZE;
43764378
bool registered = false;
43774379

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

44034405
INIT_LIST_HEAD(&alg_list);
44044406

4405-
/* register crypto algorithms the device supports */
4407+
/*
4408+
* Register crypto algorithms the device supports.
4409+
* First, detect presence and attributes of DES, AES, and MD blocks.
4410+
*/
4411+
cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
4412+
cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
4413+
des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> CHA_ID_LS_DES_SHIFT;
4414+
aes_inst = (cha_inst & CHA_ID_LS_AES_MASK) >> CHA_ID_LS_AES_SHIFT;
4415+
md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
4416+
4417+
/* If MD is present, limit digest size based on LP256 */
4418+
if (md_inst && ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256))
4419+
md_limit = SHA256_DIGEST_SIZE;
4420+
44064421
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
4407-
/* TODO: check if h/w supports alg */
44084422
struct caam_crypto_alg *t_alg;
4423+
struct caam_alg_template *alg = driver_algs + i;
4424+
u32 alg_sel = alg->class1_alg_type & OP_ALG_ALGSEL_MASK;
4425+
4426+
/* Skip DES algorithms if not supported by device */
4427+
if (!des_inst &&
4428+
((alg_sel == OP_ALG_ALGSEL_3DES) ||
4429+
(alg_sel == OP_ALG_ALGSEL_DES)))
4430+
continue;
4431+
4432+
/* Skip AES algorithms if not supported by device */
4433+
if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
4434+
continue;
44094435

4410-
t_alg = caam_alg_alloc(&driver_algs[i]);
4436+
t_alg = caam_alg_alloc(alg);
44114437
if (IS_ERR(t_alg)) {
44124438
err = PTR_ERR(t_alg);
4413-
pr_warn("%s alg allocation failed\n",
4414-
driver_algs[i].driver_name);
4439+
pr_warn("%s alg allocation failed\n", alg->driver_name);
44154440
continue;
44164441
}
44174442

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

44304455
for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) {
44314456
struct caam_aead_alg *t_alg = driver_aeads + i;
4457+
u32 c1_alg_sel = t_alg->caam.class1_alg_type &
4458+
OP_ALG_ALGSEL_MASK;
4459+
u32 c2_alg_sel = t_alg->caam.class2_alg_type &
4460+
OP_ALG_ALGSEL_MASK;
4461+
u32 alg_aai = t_alg->caam.class1_alg_type & OP_ALG_AAI_MASK;
4462+
4463+
/* Skip DES algorithms if not supported by device */
4464+
if (!des_inst &&
4465+
((c1_alg_sel == OP_ALG_ALGSEL_3DES) ||
4466+
(c1_alg_sel == OP_ALG_ALGSEL_DES)))
4467+
continue;
4468+
4469+
/* Skip AES algorithms if not supported by device */
4470+
if (!aes_inst && (c1_alg_sel == OP_ALG_ALGSEL_AES))
4471+
continue;
4472+
4473+
/*
4474+
* Check support for AES algorithms not available
4475+
* on LP devices.
4476+
*/
4477+
if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP)
4478+
if (alg_aai == OP_ALG_AAI_GCM)
4479+
continue;
4480+
4481+
/*
4482+
* Skip algorithms requiring message digests
4483+
* if MD or MD size is not supported by device.
4484+
*/
4485+
if (c2_alg_sel &&
4486+
(!md_inst || (t_alg->aead.maxauthsize > md_limit)))
4487+
continue;
44324488

44334489
caam_aead_alg_init(t_alg);
44344490

drivers/crypto/caam/caamhash.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,8 +1883,10 @@ static int __init caam_algapi_hash_init(void)
18831883
struct device_node *dev_node;
18841884
struct platform_device *pdev;
18851885
struct device *ctrldev;
1886-
void *priv;
18871886
int i = 0, err = 0;
1887+
struct caam_drv_private *priv;
1888+
unsigned int md_limit = SHA512_DIGEST_SIZE;
1889+
u32 cha_inst, cha_vid;
18881890

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

1915+
/*
1916+
* Register crypto algorithms the device supports. First, identify
1917+
* presence and attributes of MD block.
1918+
*/
1919+
cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls);
1920+
cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
1921+
1922+
/*
1923+
* Skip registration of any hashing algorithms if MD block
1924+
* is not present.
1925+
*/
1926+
if (!((cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT))
1927+
return -ENODEV;
1928+
1929+
/* Limit digest size based on LP256 */
1930+
if ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)
1931+
md_limit = SHA256_DIGEST_SIZE;
1932+
19131933
INIT_LIST_HEAD(&hash_list);
19141934

19151935
/* register crypto algorithms the device supports */
19161936
for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
1917-
/* TODO: check if h/w supports alg */
19181937
struct caam_hash_alg *t_alg;
1938+
struct caam_hash_template *alg = driver_hash + i;
1939+
1940+
/* If MD size is not supported by device, skip registration */
1941+
if (alg->template_ahash.halg.digestsize > md_limit)
1942+
continue;
19191943

19201944
/* register hmac version */
1921-
t_alg = caam_hash_alloc(&driver_hash[i], true);
1945+
t_alg = caam_hash_alloc(alg, true);
19221946
if (IS_ERR(t_alg)) {
19231947
err = PTR_ERR(t_alg);
1924-
pr_warn("%s alg allocation failed\n",
1925-
driver_hash[i].driver_name);
1948+
pr_warn("%s alg allocation failed\n", alg->driver_name);
19261949
continue;
19271950
}
19281951

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

19371960
/* register unkeyed version */
1938-
t_alg = caam_hash_alloc(&driver_hash[i], false);
1961+
t_alg = caam_hash_alloc(alg, false);
19391962
if (IS_ERR(t_alg)) {
19401963
err = PTR_ERR(t_alg);
1941-
pr_warn("%s alg allocation failed\n",
1942-
driver_hash[i].driver_name);
1964+
pr_warn("%s alg allocation failed\n", alg->driver_name);
19431965
continue;
19441966
}
19451967

drivers/crypto/caam/caamrng.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ static int __init caam_rng_init(void)
315315
struct device_node *dev_node;
316316
struct platform_device *pdev;
317317
struct device *ctrldev;
318-
void *priv;
318+
struct caam_drv_private *priv;
319319
int err;
320320

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

345+
/* Check for an instantiated RNG before registration */
346+
if (!(rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & CHA_ID_LS_RNG_MASK))
347+
return -ENODEV;
348+
345349
dev = caam_jr_alloc();
346350
if (IS_ERR(dev)) {
347351
pr_err("Job Ring Device allocation for transform failed\n");

drivers/crypto/caam/regs.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,28 @@ struct jr_outentry {
156156
#define CHA_NUM_MS_DECONUM_SHIFT 24
157157
#define CHA_NUM_MS_DECONUM_MASK (0xfull << CHA_NUM_MS_DECONUM_SHIFT)
158158

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

163170
#define CHA_ID_LS_DES_SHIFT 4
164-
#define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT)
171+
#define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT)
165172

166173
#define CHA_ID_LS_ARC4_SHIFT 8
167174
#define CHA_ID_LS_ARC4_MASK (0xfull << CHA_ID_LS_ARC4_SHIFT)
168175

169176
#define CHA_ID_LS_MD_SHIFT 12
170177
#define CHA_ID_LS_MD_MASK (0xfull << CHA_ID_LS_MD_SHIFT)
178+
#define CHA_ID_LS_MD_LP256 (0x0ull << CHA_ID_LS_MD_SHIFT)
179+
#define CHA_ID_LS_MD_LP512 (0x1ull << CHA_ID_LS_MD_SHIFT)
180+
#define CHA_ID_LS_MD_HP (0x2ull << CHA_ID_LS_MD_SHIFT)
171181

172182
#define CHA_ID_LS_RNG_SHIFT 16
173183
#define CHA_ID_LS_RNG_MASK (0xfull << CHA_ID_LS_RNG_SHIFT)

0 commit comments

Comments
 (0)