Commit f9fb69e7 authored by Mark A. Greer's avatar Mark A. Greer Committed by Herbert Xu

crypto: omap-aes - Add CTR algorithm Support

The OMAP3 and OMAP4/AM33xx versions of the AES crypto
module support the CTR algorithm in addition to ECB
and CBC that the OMAP2 version of the module supports.

So, OMAP2 and OMAP3 share a common register set but
OMAP3 supports CTR while OMAP2 doesn't.  OMAP4/AM33XX
uses a different register set from OMAP2/OMAP3 and
also supports CTR.

To add this support, use the platform_data introduced
in an ealier commit to hold the list of algorithms
supported by the current module.  The probe routine
will use that list to register the correct algorithms.

Note: The code being integrated is from the TI AM33xx SDK
and was written by Greg Turner <gkmturner@gmail.com> and
Herman Schuurman (current email unknown) while at TI.

CC: Greg Turner <gkmturner@gmail.com>
CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Signed-off-by: default avatarMark A. Greer <mgreer@animalcreek.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0d35583a
...@@ -48,7 +48,11 @@ ...@@ -48,7 +48,11 @@
#define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04)) #define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
#define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs) #define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
#define AES_REG_CTRL_CTR_WIDTH (1 << 7) #define AES_REG_CTRL_CTR_WIDTH_MASK (3 << 7)
#define AES_REG_CTRL_CTR_WIDTH_32 (0 << 7)
#define AES_REG_CTRL_CTR_WIDTH_64 (1 << 7)
#define AES_REG_CTRL_CTR_WIDTH_96 (2 << 7)
#define AES_REG_CTRL_CTR_WIDTH_128 (3 << 7)
#define AES_REG_CTRL_CTR (1 << 6) #define AES_REG_CTRL_CTR (1 << 6)
#define AES_REG_CTRL_CBC (1 << 5) #define AES_REG_CTRL_CBC (1 << 5)
#define AES_REG_CTRL_KEY_SIZE (3 << 3) #define AES_REG_CTRL_KEY_SIZE (3 << 3)
...@@ -76,6 +80,7 @@ ...@@ -76,6 +80,7 @@
#define FLAGS_ENCRYPT BIT(0) #define FLAGS_ENCRYPT BIT(0)
#define FLAGS_CBC BIT(1) #define FLAGS_CBC BIT(1)
#define FLAGS_GIV BIT(2) #define FLAGS_GIV BIT(2)
#define FLAGS_CTR BIT(3)
#define FLAGS_INIT BIT(4) #define FLAGS_INIT BIT(4)
#define FLAGS_FAST BIT(5) #define FLAGS_FAST BIT(5)
...@@ -96,7 +101,16 @@ struct omap_aes_reqctx { ...@@ -96,7 +101,16 @@ struct omap_aes_reqctx {
#define OMAP_AES_QUEUE_LENGTH 1 #define OMAP_AES_QUEUE_LENGTH 1
#define OMAP_AES_CACHE_SIZE 0 #define OMAP_AES_CACHE_SIZE 0
struct omap_aes_algs_info {
struct crypto_alg *algs_list;
unsigned int size;
unsigned int registered;
};
struct omap_aes_pdata { struct omap_aes_pdata {
struct omap_aes_algs_info *algs_info;
unsigned int algs_info_size;
void (*trigger)(struct omap_aes_dev *dd, int length); void (*trigger)(struct omap_aes_dev *dd, int length);
u32 key_ofs; u32 key_ofs;
...@@ -208,7 +222,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd) ...@@ -208,7 +222,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
{ {
unsigned int key32; unsigned int key32;
int i, err; int i, err;
u32 val, mask; u32 val, mask = 0;
err = omap_aes_hw_init(dd); err = omap_aes_hw_init(dd);
if (err) if (err)
...@@ -222,16 +236,20 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd) ...@@ -222,16 +236,20 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
__le32_to_cpu(dd->ctx->key[i])); __le32_to_cpu(dd->ctx->key[i]));
} }
if ((dd->flags & FLAGS_CBC) && dd->req->info) if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info)
omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4); omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
if (dd->flags & FLAGS_CBC) if (dd->flags & FLAGS_CBC)
val |= AES_REG_CTRL_CBC; val |= AES_REG_CTRL_CBC;
if (dd->flags & FLAGS_CTR) {
val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32;
mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
}
if (dd->flags & FLAGS_ENCRYPT) if (dd->flags & FLAGS_ENCRYPT)
val |= AES_REG_CTRL_DIRECTION; val |= AES_REG_CTRL_DIRECTION;
mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
AES_REG_CTRL_KEY_SIZE; AES_REG_CTRL_KEY_SIZE;
omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask); omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
...@@ -807,6 +825,16 @@ static int omap_aes_cbc_decrypt(struct ablkcipher_request *req) ...@@ -807,6 +825,16 @@ static int omap_aes_cbc_decrypt(struct ablkcipher_request *req)
return omap_aes_crypt(req, FLAGS_CBC); return omap_aes_crypt(req, FLAGS_CBC);
} }
static int omap_aes_ctr_encrypt(struct ablkcipher_request *req)
{
return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CTR);
}
static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
{
return omap_aes_crypt(req, FLAGS_CTR);
}
static int omap_aes_cra_init(struct crypto_tfm *tfm) static int omap_aes_cra_init(struct crypto_tfm *tfm)
{ {
pr_debug("enter\n"); pr_debug("enter\n");
...@@ -823,7 +851,7 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm) ...@@ -823,7 +851,7 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
/* ********************** ALGS ************************************ */ /* ********************** ALGS ************************************ */
static struct crypto_alg algs[] = { static struct crypto_alg algs_ecb_cbc[] = {
{ {
.cra_name = "ecb(aes)", .cra_name = "ecb(aes)",
.cra_driver_name = "ecb-aes-omap", .cra_driver_name = "ecb-aes-omap",
...@@ -871,7 +899,43 @@ static struct crypto_alg algs[] = { ...@@ -871,7 +899,43 @@ static struct crypto_alg algs[] = {
} }
}; };
static struct crypto_alg algs_ctr[] = {
{
.cra_name = "ctr(aes)",
.cra_driver_name = "ctr-aes-omap",
.cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
CRYPTO_ALG_KERN_DRIVER_ONLY |
CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
.cra_alignmask = 0,
.cra_type = &crypto_ablkcipher_type,
.cra_module = THIS_MODULE,
.cra_init = omap_aes_cra_init,
.cra_exit = omap_aes_cra_exit,
.cra_u.ablkcipher = {
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
.geniv = "eseqiv",
.ivsize = AES_BLOCK_SIZE,
.setkey = omap_aes_setkey,
.encrypt = omap_aes_ctr_encrypt,
.decrypt = omap_aes_ctr_decrypt,
}
} ,
};
static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = {
{
.algs_list = algs_ecb_cbc,
.size = ARRAY_SIZE(algs_ecb_cbc),
},
};
static const struct omap_aes_pdata omap_aes_pdata_omap2 = { static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
.algs_info = omap_aes_algs_info_ecb_cbc,
.algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc),
.trigger = omap_aes_dma_trigger_omap2, .trigger = omap_aes_dma_trigger_omap2,
.key_ofs = 0x1c, .key_ofs = 0x1c,
.iv_ofs = 0x20, .iv_ofs = 0x20,
...@@ -889,7 +953,39 @@ static const struct omap_aes_pdata omap_aes_pdata_omap2 = { ...@@ -889,7 +953,39 @@ static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc_ctr[] = {
{
.algs_list = algs_ecb_cbc,
.size = ARRAY_SIZE(algs_ecb_cbc),
},
{
.algs_list = algs_ctr,
.size = ARRAY_SIZE(algs_ctr),
},
};
static const struct omap_aes_pdata omap_aes_pdata_omap3 = {
.algs_info = omap_aes_algs_info_ecb_cbc_ctr,
.algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
.trigger = omap_aes_dma_trigger_omap2,
.key_ofs = 0x1c,
.iv_ofs = 0x20,
.ctrl_ofs = 0x30,
.data_ofs = 0x34,
.rev_ofs = 0x44,
.mask_ofs = 0x48,
.dma_enable_in = BIT(2),
.dma_enable_out = BIT(3),
.dma_start = BIT(5),
.major_mask = 0xf0,
.major_shift = 4,
.minor_mask = 0x0f,
.minor_shift = 0,
};
static const struct omap_aes_pdata omap_aes_pdata_omap4 = { static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
.algs_info = omap_aes_algs_info_ecb_cbc_ctr,
.algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
.trigger = omap_aes_dma_trigger_omap4, .trigger = omap_aes_dma_trigger_omap4,
.key_ofs = 0x3c, .key_ofs = 0x3c,
.iv_ofs = 0x40, .iv_ofs = 0x40,
...@@ -910,6 +1006,10 @@ static const struct of_device_id omap_aes_of_match[] = { ...@@ -910,6 +1006,10 @@ static const struct of_device_id omap_aes_of_match[] = {
.compatible = "ti,omap2-aes", .compatible = "ti,omap2-aes",
.data = &omap_aes_pdata_omap2, .data = &omap_aes_pdata_omap2,
}, },
{
.compatible = "ti,omap3-aes",
.data = &omap_aes_pdata_omap3,
},
{ {
.compatible = "ti,omap4-aes", .compatible = "ti,omap4-aes",
.data = &omap_aes_pdata_omap4, .data = &omap_aes_pdata_omap4,
...@@ -1004,6 +1104,7 @@ static int omap_aes_probe(struct platform_device *pdev) ...@@ -1004,6 +1104,7 @@ static int omap_aes_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct omap_aes_dev *dd; struct omap_aes_dev *dd;
struct crypto_alg *algp;
struct resource res; struct resource res;
int err = -ENOMEM, i, j; int err = -ENOMEM, i, j;
u32 reg; u32 reg;
...@@ -1057,17 +1158,27 @@ static int omap_aes_probe(struct platform_device *pdev) ...@@ -1057,17 +1158,27 @@ static int omap_aes_probe(struct platform_device *pdev)
list_add_tail(&dd->list, &dev_list); list_add_tail(&dd->list, &dev_list);
spin_unlock(&list_lock); spin_unlock(&list_lock);
for (i = 0; i < ARRAY_SIZE(algs); i++) { for (i = 0; i < dd->pdata->algs_info_size; i++) {
pr_debug("i: %d\n", i); for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
err = crypto_register_alg(&algs[i]); algp = &dd->pdata->algs_info[i].algs_list[j];
if (err)
goto err_algs; pr_debug("reg alg: %s\n", algp->cra_name);
INIT_LIST_HEAD(&algp->cra_list);
err = crypto_register_alg(algp);
if (err)
goto err_algs;
dd->pdata->algs_info[i].registered++;
}
} }
return 0; return 0;
err_algs: err_algs:
for (j = 0; j < i; j++) for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
crypto_unregister_alg(&algs[j]); for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
crypto_unregister_alg(
&dd->pdata->algs_info[i].algs_list[j]);
omap_aes_dma_cleanup(dd); omap_aes_dma_cleanup(dd);
err_dma: err_dma:
tasklet_kill(&dd->done_task); tasklet_kill(&dd->done_task);
...@@ -1084,7 +1195,7 @@ static int omap_aes_probe(struct platform_device *pdev) ...@@ -1084,7 +1195,7 @@ static int omap_aes_probe(struct platform_device *pdev)
static int omap_aes_remove(struct platform_device *pdev) static int omap_aes_remove(struct platform_device *pdev)
{ {
struct omap_aes_dev *dd = platform_get_drvdata(pdev); struct omap_aes_dev *dd = platform_get_drvdata(pdev);
int i; int i, j;
if (!dd) if (!dd)
return -ENODEV; return -ENODEV;
...@@ -1093,8 +1204,10 @@ static int omap_aes_remove(struct platform_device *pdev) ...@@ -1093,8 +1204,10 @@ static int omap_aes_remove(struct platform_device *pdev)
list_del(&dd->list); list_del(&dd->list);
spin_unlock(&list_lock); spin_unlock(&list_lock);
for (i = 0; i < ARRAY_SIZE(algs); i++) for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
crypto_unregister_alg(&algs[i]); for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
crypto_unregister_alg(
&dd->pdata->algs_info[i].algs_list[j]);
tasklet_kill(&dd->done_task); tasklet_kill(&dd->done_task);
tasklet_kill(&dd->queue_task); tasklet_kill(&dd->queue_task);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment