diff options
-rw-r--r-- | drivers/crypto/omap-aes.c | 143 |
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 | ||
104 | struct omap_aes_algs_info { | ||
105 | struct crypto_alg *algs_list; | ||
106 | unsigned int size; | ||
107 | unsigned int registered; | ||
108 | }; | ||
109 | |||
99 | struct omap_aes_pdata { | 110 | struct 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 | ||
828 | static int omap_aes_ctr_encrypt(struct ablkcipher_request *req) | ||
829 | { | ||
830 | return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CTR); | ||
831 | } | ||
832 | |||
833 | static int omap_aes_ctr_decrypt(struct ablkcipher_request *req) | ||
834 | { | ||
835 | return omap_aes_crypt(req, FLAGS_CTR); | ||
836 | } | ||
837 | |||
810 | static int omap_aes_cra_init(struct crypto_tfm *tfm) | 838 | static 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 | ||
826 | static struct crypto_alg algs[] = { | 854 | static 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 | ||
902 | static 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 | |||
929 | static 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 | |||
874 | static const struct omap_aes_pdata omap_aes_pdata_omap2 = { | 936 | static 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 |
956 | static 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 | |||
967 | static 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 | |||
892 | static const struct omap_aes_pdata omap_aes_pdata_omap4 = { | 986 | static 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; |
1068 | err_algs: | 1177 | err_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); |
1072 | err_dma: | 1183 | err_dma: |
1073 | tasklet_kill(&dd->done_task); | 1184 | tasklet_kill(&dd->done_task); |
@@ -1084,7 +1195,7 @@ err_data: | |||
1084 | static int omap_aes_remove(struct platform_device *pdev) | 1195 | static 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); |