aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2013-01-08 13:57:47 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-01-19 18:16:44 -0500
commitf9fb69e73c774a6490a13128381af9ba468d3a6e (patch)
treecc6c267aea1557f7aeb0b7ba7cc377f5262d86b2 /drivers/crypto
parent0d35583a13ad29af06375678daa2e11772ec9267 (diff)
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: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/omap-aes.c143
1 files changed, 128 insertions, 15 deletions
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index bd1ad97404ab..6aa425fe0ed5 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -48,7 +48,11 @@
48#define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04)) 48#define AES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04))
49 49
50#define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs) 50#define AES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs)
51#define AES_REG_CTRL_CTR_WIDTH (1 << 7) 51#define AES_REG_CTRL_CTR_WIDTH_MASK (3 << 7)
52#define AES_REG_CTRL_CTR_WIDTH_32 (0 << 7)
53#define AES_REG_CTRL_CTR_WIDTH_64 (1 << 7)
54#define AES_REG_CTRL_CTR_WIDTH_96 (2 << 7)
55#define AES_REG_CTRL_CTR_WIDTH_128 (3 << 7)
52#define AES_REG_CTRL_CTR (1 << 6) 56#define AES_REG_CTRL_CTR (1 << 6)
53#define AES_REG_CTRL_CBC (1 << 5) 57#define AES_REG_CTRL_CBC (1 << 5)
54#define AES_REG_CTRL_KEY_SIZE (3 << 3) 58#define AES_REG_CTRL_KEY_SIZE (3 << 3)
@@ -76,6 +80,7 @@
76#define FLAGS_ENCRYPT BIT(0) 80#define FLAGS_ENCRYPT BIT(0)
77#define FLAGS_CBC BIT(1) 81#define FLAGS_CBC BIT(1)
78#define FLAGS_GIV BIT(2) 82#define FLAGS_GIV BIT(2)
83#define FLAGS_CTR BIT(3)
79 84
80#define FLAGS_INIT BIT(4) 85#define FLAGS_INIT BIT(4)
81#define FLAGS_FAST BIT(5) 86#define FLAGS_FAST BIT(5)
@@ -96,7 +101,16 @@ struct omap_aes_reqctx {
96#define OMAP_AES_QUEUE_LENGTH 1 101#define OMAP_AES_QUEUE_LENGTH 1
97#define OMAP_AES_CACHE_SIZE 0 102#define OMAP_AES_CACHE_SIZE 0
98 103
104struct omap_aes_algs_info {
105 struct crypto_alg *algs_list;
106 unsigned int size;
107 unsigned int registered;
108};
109
99struct omap_aes_pdata { 110struct omap_aes_pdata {
111 struct omap_aes_algs_info *algs_info;
112 unsigned int algs_info_size;
113
100 void (*trigger)(struct omap_aes_dev *dd, int length); 114 void (*trigger)(struct omap_aes_dev *dd, int length);
101 115
102 u32 key_ofs; 116 u32 key_ofs;
@@ -208,7 +222,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
208{ 222{
209 unsigned int key32; 223 unsigned int key32;
210 int i, err; 224 int i, err;
211 u32 val, mask; 225 u32 val, mask = 0;
212 226
213 err = omap_aes_hw_init(dd); 227 err = omap_aes_hw_init(dd);
214 if (err) 228 if (err)
@@ -222,16 +236,20 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
222 __le32_to_cpu(dd->ctx->key[i])); 236 __le32_to_cpu(dd->ctx->key[i]));
223 } 237 }
224 238
225 if ((dd->flags & FLAGS_CBC) && dd->req->info) 239 if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info)
226 omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4); 240 omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
227 241
228 val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); 242 val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
229 if (dd->flags & FLAGS_CBC) 243 if (dd->flags & FLAGS_CBC)
230 val |= AES_REG_CTRL_CBC; 244 val |= AES_REG_CTRL_CBC;
245 if (dd->flags & FLAGS_CTR) {
246 val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32;
247 mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
248 }
231 if (dd->flags & FLAGS_ENCRYPT) 249 if (dd->flags & FLAGS_ENCRYPT)
232 val |= AES_REG_CTRL_DIRECTION; 250 val |= AES_REG_CTRL_DIRECTION;
233 251
234 mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | 252 mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
235 AES_REG_CTRL_KEY_SIZE; 253 AES_REG_CTRL_KEY_SIZE;
236 254
237 omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask); 255 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 return omap_aes_crypt(req, FLAGS_CBC); 825 return omap_aes_crypt(req, FLAGS_CBC);
808} 826}
809 827
828static int omap_aes_ctr_encrypt(struct ablkcipher_request *req)
829{
830 return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CTR);
831}
832
833static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
834{
835 return omap_aes_crypt(req, FLAGS_CTR);
836}
837
810static int omap_aes_cra_init(struct crypto_tfm *tfm) 838static int omap_aes_cra_init(struct crypto_tfm *tfm)
811{ 839{
812 pr_debug("enter\n"); 840 pr_debug("enter\n");
@@ -823,7 +851,7 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
823 851
824/* ********************** ALGS ************************************ */ 852/* ********************** ALGS ************************************ */
825 853
826static struct crypto_alg algs[] = { 854static struct crypto_alg algs_ecb_cbc[] = {
827{ 855{
828 .cra_name = "ecb(aes)", 856 .cra_name = "ecb(aes)",
829 .cra_driver_name = "ecb-aes-omap", 857 .cra_driver_name = "ecb-aes-omap",
@@ -871,7 +899,43 @@ static struct crypto_alg algs[] = {
871} 899}
872}; 900};
873 901
902static struct crypto_alg algs_ctr[] = {
903{
904 .cra_name = "ctr(aes)",
905 .cra_driver_name = "ctr-aes-omap",
906 .cra_priority = 100,
907 .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
908 CRYPTO_ALG_KERN_DRIVER_ONLY |
909 CRYPTO_ALG_ASYNC,
910 .cra_blocksize = AES_BLOCK_SIZE,
911 .cra_ctxsize = sizeof(struct omap_aes_ctx),
912 .cra_alignmask = 0,
913 .cra_type = &crypto_ablkcipher_type,
914 .cra_module = THIS_MODULE,
915 .cra_init = omap_aes_cra_init,
916 .cra_exit = omap_aes_cra_exit,
917 .cra_u.ablkcipher = {
918 .min_keysize = AES_MIN_KEY_SIZE,
919 .max_keysize = AES_MAX_KEY_SIZE,
920 .geniv = "eseqiv",
921 .ivsize = AES_BLOCK_SIZE,
922 .setkey = omap_aes_setkey,
923 .encrypt = omap_aes_ctr_encrypt,
924 .decrypt = omap_aes_ctr_decrypt,
925 }
926} ,
927};
928
929static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = {
930 {
931 .algs_list = algs_ecb_cbc,
932 .size = ARRAY_SIZE(algs_ecb_cbc),
933 },
934};
935
874static const struct omap_aes_pdata omap_aes_pdata_omap2 = { 936static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
937 .algs_info = omap_aes_algs_info_ecb_cbc,
938 .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc),
875 .trigger = omap_aes_dma_trigger_omap2, 939 .trigger = omap_aes_dma_trigger_omap2,
876 .key_ofs = 0x1c, 940 .key_ofs = 0x1c,
877 .iv_ofs = 0x20, 941 .iv_ofs = 0x20,
@@ -889,7 +953,39 @@ static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
889}; 953};
890 954
891#ifdef CONFIG_OF 955#ifdef CONFIG_OF
956static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc_ctr[] = {
957 {
958 .algs_list = algs_ecb_cbc,
959 .size = ARRAY_SIZE(algs_ecb_cbc),
960 },
961 {
962 .algs_list = algs_ctr,
963 .size = ARRAY_SIZE(algs_ctr),
964 },
965};
966
967static const struct omap_aes_pdata omap_aes_pdata_omap3 = {
968 .algs_info = omap_aes_algs_info_ecb_cbc_ctr,
969 .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
970 .trigger = omap_aes_dma_trigger_omap2,
971 .key_ofs = 0x1c,
972 .iv_ofs = 0x20,
973 .ctrl_ofs = 0x30,
974 .data_ofs = 0x34,
975 .rev_ofs = 0x44,
976 .mask_ofs = 0x48,
977 .dma_enable_in = BIT(2),
978 .dma_enable_out = BIT(3),
979 .dma_start = BIT(5),
980 .major_mask = 0xf0,
981 .major_shift = 4,
982 .minor_mask = 0x0f,
983 .minor_shift = 0,
984};
985
892static const struct omap_aes_pdata omap_aes_pdata_omap4 = { 986static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
987 .algs_info = omap_aes_algs_info_ecb_cbc_ctr,
988 .algs_info_size = ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
893 .trigger = omap_aes_dma_trigger_omap4, 989 .trigger = omap_aes_dma_trigger_omap4,
894 .key_ofs = 0x3c, 990 .key_ofs = 0x3c,
895 .iv_ofs = 0x40, 991 .iv_ofs = 0x40,
@@ -911,6 +1007,10 @@ static const struct of_device_id omap_aes_of_match[] = {
911 .data = &omap_aes_pdata_omap2, 1007 .data = &omap_aes_pdata_omap2,
912 }, 1008 },
913 { 1009 {
1010 .compatible = "ti,omap3-aes",
1011 .data = &omap_aes_pdata_omap3,
1012 },
1013 {
914 .compatible = "ti,omap4-aes", 1014 .compatible = "ti,omap4-aes",
915 .data = &omap_aes_pdata_omap4, 1015 .data = &omap_aes_pdata_omap4,
916 }, 1016 },
@@ -1004,6 +1104,7 @@ static int omap_aes_probe(struct platform_device *pdev)
1004{ 1104{
1005 struct device *dev = &pdev->dev; 1105 struct device *dev = &pdev->dev;
1006 struct omap_aes_dev *dd; 1106 struct omap_aes_dev *dd;
1107 struct crypto_alg *algp;
1007 struct resource res; 1108 struct resource res;
1008 int err = -ENOMEM, i, j; 1109 int err = -ENOMEM, i, j;
1009 u32 reg; 1110 u32 reg;
@@ -1057,17 +1158,27 @@ static int omap_aes_probe(struct platform_device *pdev)
1057 list_add_tail(&dd->list, &dev_list); 1158 list_add_tail(&dd->list, &dev_list);
1058 spin_unlock(&list_lock); 1159 spin_unlock(&list_lock);
1059 1160
1060 for (i = 0; i < ARRAY_SIZE(algs); i++) { 1161 for (i = 0; i < dd->pdata->algs_info_size; i++) {
1061 pr_debug("i: %d\n", i); 1162 for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
1062 err = crypto_register_alg(&algs[i]); 1163 algp = &dd->pdata->algs_info[i].algs_list[j];
1063 if (err) 1164
1064 goto err_algs; 1165 pr_debug("reg alg: %s\n", algp->cra_name);
1166 INIT_LIST_HEAD(&algp->cra_list);
1167
1168 err = crypto_register_alg(algp);
1169 if (err)
1170 goto err_algs;
1171
1172 dd->pdata->algs_info[i].registered++;
1173 }
1065 } 1174 }
1066 1175
1067 return 0; 1176 return 0;
1068err_algs: 1177err_algs:
1069 for (j = 0; j < i; j++) 1178 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1070 crypto_unregister_alg(&algs[j]); 1179 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1180 crypto_unregister_alg(
1181 &dd->pdata->algs_info[i].algs_list[j]);
1071 omap_aes_dma_cleanup(dd); 1182 omap_aes_dma_cleanup(dd);
1072err_dma: 1183err_dma:
1073 tasklet_kill(&dd->done_task); 1184 tasklet_kill(&dd->done_task);
@@ -1084,7 +1195,7 @@ err_data:
1084static int omap_aes_remove(struct platform_device *pdev) 1195static int omap_aes_remove(struct platform_device *pdev)
1085{ 1196{
1086 struct omap_aes_dev *dd = platform_get_drvdata(pdev); 1197 struct omap_aes_dev *dd = platform_get_drvdata(pdev);
1087 int i; 1198 int i, j;
1088 1199
1089 if (!dd) 1200 if (!dd)
1090 return -ENODEV; 1201 return -ENODEV;
@@ -1093,8 +1204,10 @@ static int omap_aes_remove(struct platform_device *pdev)
1093 list_del(&dd->list); 1204 list_del(&dd->list);
1094 spin_unlock(&list_lock); 1205 spin_unlock(&list_lock);
1095 1206
1096 for (i = 0; i < ARRAY_SIZE(algs); i++) 1207 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1097 crypto_unregister_alg(&algs[i]); 1208 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1209 crypto_unregister_alg(
1210 &dd->pdata->algs_info[i].algs_list[j]);
1098 1211
1099 tasklet_kill(&dd->done_task); 1212 tasklet_kill(&dd->done_task);
1100 tasklet_kill(&dd->queue_task); 1213 tasklet_kill(&dd->queue_task);