aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/omap-sham.c
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2012-12-21 12:04:09 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-01-05 05:43:58 -0500
commitd20fb18be246d196225ed151c126832b2dab6506 (patch)
tree010c6547d2e2c289f652691ecf73846a38242eee /drivers/crypto/omap-sham.c
parent0d373d603202b8bfecc87b9b3602e6ffbf9e4feb (diff)
crypto: omap-sham - Add SHA224 and SHA256 Support
The OMAP4/AM33xx version of the SHAM crypto module supports SHA224 and SHA256 in addition to MD5 and SHA1 that the OMAP2 version of the module supports. 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/omap-sham.c')
-rw-r--r--drivers/crypto/omap-sham.c183
1 files changed, 173 insertions, 10 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index fab0af488b83..edff981edfb1 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -83,6 +83,8 @@
83#define SHA_REG_MODE_ALGO_MASK (3 << 1) 83#define SHA_REG_MODE_ALGO_MASK (3 << 1)
84#define SHA_REG_MODE_ALGO_MD5_128 (0 << 1) 84#define SHA_REG_MODE_ALGO_MD5_128 (0 << 1)
85#define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1) 85#define SHA_REG_MODE_ALGO_SHA1_160 (1 << 1)
86#define SHA_REG_MODE_ALGO_SHA2_224 (2 << 1)
87#define SHA_REG_MODE_ALGO_SHA2_256 (3 << 1)
86 88
87#define SHA_REG_LENGTH 0x48 89#define SHA_REG_LENGTH 0x48
88 90
@@ -121,6 +123,10 @@
121 << (FLAGS_MODE_SHIFT - 1)) 123 << (FLAGS_MODE_SHIFT - 1))
122#define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 \ 124#define FLAGS_MODE_SHA1 (SHA_REG_MODE_ALGO_SHA1_160 \
123 << (FLAGS_MODE_SHIFT - 1)) 125 << (FLAGS_MODE_SHIFT - 1))
126#define FLAGS_MODE_SHA224 (SHA_REG_MODE_ALGO_SHA2_224 \
127 << (FLAGS_MODE_SHIFT - 1))
128#define FLAGS_MODE_SHA256 (SHA_REG_MODE_ALGO_SHA2_256 \
129 << (FLAGS_MODE_SHIFT - 1))
124#define FLAGS_HMAC 20 130#define FLAGS_HMAC 20
125#define FLAGS_ERROR 21 131#define FLAGS_ERROR 21
126 132
@@ -173,7 +179,15 @@ struct omap_sham_ctx {
173 179
174#define OMAP_SHAM_QUEUE_LENGTH 1 180#define OMAP_SHAM_QUEUE_LENGTH 1
175 181
182struct omap_sham_algs_info {
183 struct ahash_alg *algs_list;
184 unsigned int size;
185 unsigned int registered;
186};
187
176struct omap_sham_pdata { 188struct omap_sham_pdata {
189 struct omap_sham_algs_info *algs_info;
190 unsigned int algs_info_size;
177 unsigned long flags; 191 unsigned long flags;
178 int digest_size; 192 int digest_size;
179 193
@@ -322,6 +336,12 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
322 big_endian = 1; 336 big_endian = 1;
323 d = SHA1_DIGEST_SIZE / sizeof(u32); 337 d = SHA1_DIGEST_SIZE / sizeof(u32);
324 break; 338 break;
339 case FLAGS_MODE_SHA224:
340 d = SHA224_DIGEST_SIZE / sizeof(u32);
341 break;
342 case FLAGS_MODE_SHA256:
343 d = SHA256_DIGEST_SIZE / sizeof(u32);
344 break;
325 default: 345 default:
326 d = 0; 346 d = 0;
327 } 347 }
@@ -780,6 +800,12 @@ static int omap_sham_init(struct ahash_request *req)
780 case SHA1_DIGEST_SIZE: 800 case SHA1_DIGEST_SIZE:
781 ctx->flags |= FLAGS_MODE_SHA1; 801 ctx->flags |= FLAGS_MODE_SHA1;
782 break; 802 break;
803 case SHA224_DIGEST_SIZE:
804 ctx->flags |= FLAGS_MODE_SHA224;
805 break;
806 case SHA256_DIGEST_SIZE:
807 ctx->flags |= FLAGS_MODE_SHA256;
808 break;
783 } 809 }
784 810
785 ctx->bufcnt = 0; 811 ctx->bufcnt = 0;
@@ -1173,6 +1199,16 @@ static int omap_sham_cra_sha1_init(struct crypto_tfm *tfm)
1173 return omap_sham_cra_init_alg(tfm, "sha1"); 1199 return omap_sham_cra_init_alg(tfm, "sha1");
1174} 1200}
1175 1201
1202static int omap_sham_cra_sha224_init(struct crypto_tfm *tfm)
1203{
1204 return omap_sham_cra_init_alg(tfm, "sha224");
1205}
1206
1207static int omap_sham_cra_sha256_init(struct crypto_tfm *tfm)
1208{
1209 return omap_sham_cra_init_alg(tfm, "sha256");
1210}
1211
1176static int omap_sham_cra_md5_init(struct crypto_tfm *tfm) 1212static int omap_sham_cra_md5_init(struct crypto_tfm *tfm)
1177{ 1213{
1178 return omap_sham_cra_init_alg(tfm, "md5"); 1214 return omap_sham_cra_init_alg(tfm, "md5");
@@ -1191,7 +1227,7 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
1191 } 1227 }
1192} 1228}
1193 1229
1194static struct ahash_alg algs[] = { 1230static struct ahash_alg algs_sha1_md5[] = {
1195{ 1231{
1196 .init = omap_sham_init, 1232 .init = omap_sham_init,
1197 .update = omap_sham_update, 1233 .update = omap_sham_update,
@@ -1290,6 +1326,102 @@ static struct ahash_alg algs[] = {
1290} 1326}
1291}; 1327};
1292 1328
1329/* OMAP4 has some algs in addition to what OMAP2 has */
1330static struct ahash_alg algs_sha224_sha256[] = {
1331{
1332 .init = omap_sham_init,
1333 .update = omap_sham_update,
1334 .final = omap_sham_final,
1335 .finup = omap_sham_finup,
1336 .digest = omap_sham_digest,
1337 .halg.digestsize = SHA224_DIGEST_SIZE,
1338 .halg.base = {
1339 .cra_name = "sha224",
1340 .cra_driver_name = "omap-sha224",
1341 .cra_priority = 100,
1342 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
1343 CRYPTO_ALG_ASYNC |
1344 CRYPTO_ALG_NEED_FALLBACK,
1345 .cra_blocksize = SHA224_BLOCK_SIZE,
1346 .cra_ctxsize = sizeof(struct omap_sham_ctx),
1347 .cra_alignmask = 0,
1348 .cra_module = THIS_MODULE,
1349 .cra_init = omap_sham_cra_init,
1350 .cra_exit = omap_sham_cra_exit,
1351 }
1352},
1353{
1354 .init = omap_sham_init,
1355 .update = omap_sham_update,
1356 .final = omap_sham_final,
1357 .finup = omap_sham_finup,
1358 .digest = omap_sham_digest,
1359 .halg.digestsize = SHA256_DIGEST_SIZE,
1360 .halg.base = {
1361 .cra_name = "sha256",
1362 .cra_driver_name = "omap-sha256",
1363 .cra_priority = 100,
1364 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
1365 CRYPTO_ALG_ASYNC |
1366 CRYPTO_ALG_NEED_FALLBACK,
1367 .cra_blocksize = SHA256_BLOCK_SIZE,
1368 .cra_ctxsize = sizeof(struct omap_sham_ctx),
1369 .cra_alignmask = 0,
1370 .cra_module = THIS_MODULE,
1371 .cra_init = omap_sham_cra_init,
1372 .cra_exit = omap_sham_cra_exit,
1373 }
1374},
1375{
1376 .init = omap_sham_init,
1377 .update = omap_sham_update,
1378 .final = omap_sham_final,
1379 .finup = omap_sham_finup,
1380 .digest = omap_sham_digest,
1381 .setkey = omap_sham_setkey,
1382 .halg.digestsize = SHA224_DIGEST_SIZE,
1383 .halg.base = {
1384 .cra_name = "hmac(sha224)",
1385 .cra_driver_name = "omap-hmac-sha224",
1386 .cra_priority = 100,
1387 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
1388 CRYPTO_ALG_ASYNC |
1389 CRYPTO_ALG_NEED_FALLBACK,
1390 .cra_blocksize = SHA224_BLOCK_SIZE,
1391 .cra_ctxsize = sizeof(struct omap_sham_ctx) +
1392 sizeof(struct omap_sham_hmac_ctx),
1393 .cra_alignmask = OMAP_ALIGN_MASK,
1394 .cra_module = THIS_MODULE,
1395 .cra_init = omap_sham_cra_sha224_init,
1396 .cra_exit = omap_sham_cra_exit,
1397 }
1398},
1399{
1400 .init = omap_sham_init,
1401 .update = omap_sham_update,
1402 .final = omap_sham_final,
1403 .finup = omap_sham_finup,
1404 .digest = omap_sham_digest,
1405 .setkey = omap_sham_setkey,
1406 .halg.digestsize = SHA256_DIGEST_SIZE,
1407 .halg.base = {
1408 .cra_name = "hmac(sha256)",
1409 .cra_driver_name = "omap-hmac-sha256",
1410 .cra_priority = 100,
1411 .cra_flags = CRYPTO_ALG_TYPE_AHASH |
1412 CRYPTO_ALG_ASYNC |
1413 CRYPTO_ALG_NEED_FALLBACK,
1414 .cra_blocksize = SHA256_BLOCK_SIZE,
1415 .cra_ctxsize = sizeof(struct omap_sham_ctx) +
1416 sizeof(struct omap_sham_hmac_ctx),
1417 .cra_alignmask = OMAP_ALIGN_MASK,
1418 .cra_module = THIS_MODULE,
1419 .cra_init = omap_sham_cra_sha256_init,
1420 .cra_exit = omap_sham_cra_exit,
1421 }
1422},
1423};
1424
1293static void omap_sham_done_task(unsigned long data) 1425static void omap_sham_done_task(unsigned long data)
1294{ 1426{
1295 struct omap_sham_dev *dd = (struct omap_sham_dev *)data; 1427 struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
@@ -1364,7 +1496,16 @@ static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
1364 return omap_sham_irq_common(dd); 1496 return omap_sham_irq_common(dd);
1365} 1497}
1366 1498
1499static struct omap_sham_algs_info omap_sham_algs_info_omap2[] = {
1500 {
1501 .algs_list = algs_sha1_md5,
1502 .size = ARRAY_SIZE(algs_sha1_md5),
1503 },
1504};
1505
1367static const struct omap_sham_pdata omap_sham_pdata_omap2 = { 1506static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
1507 .algs_info = omap_sham_algs_info_omap2,
1508 .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap2),
1368 .flags = BIT(FLAGS_BE32_SHA1), 1509 .flags = BIT(FLAGS_BE32_SHA1),
1369 .digest_size = SHA1_DIGEST_SIZE, 1510 .digest_size = SHA1_DIGEST_SIZE,
1370 .copy_hash = omap_sham_copy_hash_omap2, 1511 .copy_hash = omap_sham_copy_hash_omap2,
@@ -1385,7 +1526,20 @@ static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
1385}; 1526};
1386 1527
1387#ifdef CONFIG_OF 1528#ifdef CONFIG_OF
1529static struct omap_sham_algs_info omap_sham_algs_info_omap4[] = {
1530 {
1531 .algs_list = algs_sha1_md5,
1532 .size = ARRAY_SIZE(algs_sha1_md5),
1533 },
1534 {
1535 .algs_list = algs_sha224_sha256,
1536 .size = ARRAY_SIZE(algs_sha224_sha256),
1537 },
1538};
1539
1388static const struct omap_sham_pdata omap_sham_pdata_omap4 = { 1540static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
1541 .algs_info = omap_sham_algs_info_omap4,
1542 .algs_info_size = ARRAY_SIZE(omap_sham_algs_info_omap4),
1389 .flags = BIT(FLAGS_AUTO_XOR), 1543 .flags = BIT(FLAGS_AUTO_XOR),
1390 .digest_size = SHA256_DIGEST_SIZE, 1544 .digest_size = SHA256_DIGEST_SIZE,
1391 .copy_hash = omap_sham_copy_hash_omap4, 1545 .copy_hash = omap_sham_copy_hash_omap4,
@@ -1570,17 +1724,24 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
1570 list_add_tail(&dd->list, &sham.dev_list); 1724 list_add_tail(&dd->list, &sham.dev_list);
1571 spin_unlock(&sham.lock); 1725 spin_unlock(&sham.lock);
1572 1726
1573 for (i = 0; i < ARRAY_SIZE(algs); i++) { 1727 for (i = 0; i < dd->pdata->algs_info_size; i++) {
1574 err = crypto_register_ahash(&algs[i]); 1728 for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
1575 if (err) 1729 err = crypto_register_ahash(
1576 goto err_algs; 1730 &dd->pdata->algs_info[i].algs_list[j]);
1731 if (err)
1732 goto err_algs;
1733
1734 dd->pdata->algs_info[i].registered++;
1735 }
1577 } 1736 }
1578 1737
1579 return 0; 1738 return 0;
1580 1739
1581err_algs: 1740err_algs:
1582 for (j = 0; j < i; j++) 1741 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1583 crypto_unregister_ahash(&algs[j]); 1742 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1743 crypto_unregister_ahash(
1744 &dd->pdata->algs_info[i].algs_list[j]);
1584 pm_runtime_disable(dev); 1745 pm_runtime_disable(dev);
1585 dma_release_channel(dd->dma_lch); 1746 dma_release_channel(dd->dma_lch);
1586dma_err: 1747dma_err:
@@ -1597,7 +1758,7 @@ data_err:
1597static int __devexit omap_sham_remove(struct platform_device *pdev) 1758static int __devexit omap_sham_remove(struct platform_device *pdev)
1598{ 1759{
1599 static struct omap_sham_dev *dd; 1760 static struct omap_sham_dev *dd;
1600 int i; 1761 int i, j;
1601 1762
1602 dd = platform_get_drvdata(pdev); 1763 dd = platform_get_drvdata(pdev);
1603 if (!dd) 1764 if (!dd)
@@ -1605,8 +1766,10 @@ static int __devexit omap_sham_remove(struct platform_device *pdev)
1605 spin_lock(&sham.lock); 1766 spin_lock(&sham.lock);
1606 list_del(&dd->list); 1767 list_del(&dd->list);
1607 spin_unlock(&sham.lock); 1768 spin_unlock(&sham.lock);
1608 for (i = 0; i < ARRAY_SIZE(algs); i++) 1769 for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
1609 crypto_unregister_ahash(&algs[i]); 1770 for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
1771 crypto_unregister_ahash(
1772 &dd->pdata->algs_info[i].algs_list[j]);
1610 tasklet_kill(&dd->done_task); 1773 tasklet_kill(&dd->done_task);
1611 pm_runtime_disable(&pdev->dev); 1774 pm_runtime_disable(&pdev->dev);
1612 dma_release_channel(dd->dma_lch); 1775 dma_release_channel(dd->dma_lch);