diff options
author | Catalin Vasile <catalin.vasile@freescale.com> | 2014-10-31 06:45:36 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2014-11-06 10:15:04 -0500 |
commit | a5f57cffce8af8d2c11204b4e289543021c73766 (patch) | |
tree | 08ec752fd9a894b33437827a7c7bf1e46f3d337e /drivers/crypto | |
parent | 2b22f6c547f90e1a41e3f39ad8d569e3efc74d42 (diff) |
crypto: caam - add support for rfc3686(ctr(aes))
Add support for Advanced Encryption Standard (AES) in Counter Mode (CTR)
as provided in IPsec implementation standard RFC3686.
ablkcipher shared descriptors now save context registers after job
execution. This is used to load Nonce specific to RFC3686 only at
first execution of shared job descriptor.
Signed-off-by: Catalin Vasile <catalin.vasile@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/caam/caamalg.c | 83 | ||||
-rw-r--r-- | drivers/crypto/caam/compat.h | 1 |
2 files changed, 79 insertions, 5 deletions
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 2dc85f8304bb..e9a4fd16031d 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c | |||
@@ -1735,14 +1735,19 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1735 | const u8 *key, unsigned int keylen) | 1735 | const u8 *key, unsigned int keylen) |
1736 | { | 1736 | { |
1737 | struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); | 1737 | struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); |
1738 | struct ablkcipher_tfm *tfm = &ablkcipher->base.crt_ablkcipher; | 1738 | struct ablkcipher_tfm *crt = &ablkcipher->base.crt_ablkcipher; |
1739 | struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablkcipher); | ||
1740 | const char *alg_name = crypto_tfm_alg_name(tfm); | ||
1739 | struct device *jrdev = ctx->jrdev; | 1741 | struct device *jrdev = ctx->jrdev; |
1740 | int ret = 0; | 1742 | int ret = 0; |
1741 | u32 *key_jump_cmd; | 1743 | u32 *key_jump_cmd; |
1742 | u32 *desc; | 1744 | u32 *desc; |
1745 | u32 *nonce; | ||
1743 | u32 ctx1_iv_off = 0; | 1746 | u32 ctx1_iv_off = 0; |
1744 | const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == | 1747 | const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == |
1745 | OP_ALG_AAI_CTR_MOD128); | 1748 | OP_ALG_AAI_CTR_MOD128); |
1749 | const bool is_rfc3686 = (ctr_mode && | ||
1750 | (strstr(alg_name, "rfc3686") != NULL)); | ||
1746 | 1751 | ||
1747 | #ifdef DEBUG | 1752 | #ifdef DEBUG |
1748 | print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ", | 1753 | print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ", |
@@ -1756,6 +1761,16 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1756 | if (ctr_mode) | 1761 | if (ctr_mode) |
1757 | ctx1_iv_off = 16; | 1762 | ctx1_iv_off = 16; |
1758 | 1763 | ||
1764 | /* | ||
1765 | * RFC3686 specific: | ||
1766 | * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} | ||
1767 | * | *key = {KEY, NONCE} | ||
1768 | */ | ||
1769 | if (is_rfc3686) { | ||
1770 | ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; | ||
1771 | keylen -= CTR_RFC3686_NONCE_SIZE; | ||
1772 | } | ||
1773 | |||
1759 | memcpy(ctx->key, key, keylen); | 1774 | memcpy(ctx->key, key, keylen); |
1760 | ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen, | 1775 | ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen, |
1761 | DMA_TO_DEVICE); | 1776 | DMA_TO_DEVICE); |
@@ -1767,7 +1782,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1767 | 1782 | ||
1768 | /* ablkcipher_encrypt shared descriptor */ | 1783 | /* ablkcipher_encrypt shared descriptor */ |
1769 | desc = ctx->sh_desc_enc; | 1784 | desc = ctx->sh_desc_enc; |
1770 | init_sh_desc(desc, HDR_SHARE_SERIAL); | 1785 | init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX); |
1771 | /* Skip if already shared */ | 1786 | /* Skip if already shared */ |
1772 | key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | | 1787 | key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | |
1773 | JUMP_COND_SHRD); | 1788 | JUMP_COND_SHRD); |
@@ -1777,12 +1792,32 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1777 | ctx->enckeylen, CLASS_1 | | 1792 | ctx->enckeylen, CLASS_1 | |
1778 | KEY_DEST_CLASS_REG); | 1793 | KEY_DEST_CLASS_REG); |
1779 | 1794 | ||
1795 | /* Load nonce into CONTEXT1 reg */ | ||
1796 | if (is_rfc3686) { | ||
1797 | nonce = (u32 *)(key + keylen); | ||
1798 | append_load_imm_u32(desc, *nonce, LDST_CLASS_IND_CCB | | ||
1799 | LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM); | ||
1800 | append_move(desc, MOVE_WAITCOMP | | ||
1801 | MOVE_SRC_OUTFIFO | | ||
1802 | MOVE_DEST_CLASS1CTX | | ||
1803 | (16 << MOVE_OFFSET_SHIFT) | | ||
1804 | (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT)); | ||
1805 | } | ||
1806 | |||
1780 | set_jump_tgt_here(desc, key_jump_cmd); | 1807 | set_jump_tgt_here(desc, key_jump_cmd); |
1781 | 1808 | ||
1782 | /* Load iv */ | 1809 | /* Load iv */ |
1783 | append_seq_load(desc, tfm->ivsize, LDST_SRCDST_BYTE_CONTEXT | | 1810 | append_seq_load(desc, crt->ivsize, LDST_SRCDST_BYTE_CONTEXT | |
1784 | LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT)); | 1811 | LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT)); |
1785 | 1812 | ||
1813 | /* Load counter into CONTEXT1 reg */ | ||
1814 | if (is_rfc3686) | ||
1815 | append_load_imm_u32(desc, be32_to_cpu(1), LDST_IMM | | ||
1816 | LDST_CLASS_1_CCB | | ||
1817 | LDST_SRCDST_BYTE_CONTEXT | | ||
1818 | ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) << | ||
1819 | LDST_OFFSET_SHIFT)); | ||
1820 | |||
1786 | /* Load operation */ | 1821 | /* Load operation */ |
1787 | append_operation(desc, ctx->class1_alg_type | | 1822 | append_operation(desc, ctx->class1_alg_type | |
1788 | OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); | 1823 | OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT); |
@@ -1806,7 +1841,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1806 | /* ablkcipher_decrypt shared descriptor */ | 1841 | /* ablkcipher_decrypt shared descriptor */ |
1807 | desc = ctx->sh_desc_dec; | 1842 | desc = ctx->sh_desc_dec; |
1808 | 1843 | ||
1809 | init_sh_desc(desc, HDR_SHARE_SERIAL); | 1844 | init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX); |
1810 | /* Skip if already shared */ | 1845 | /* Skip if already shared */ |
1811 | key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | | 1846 | key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | |
1812 | JUMP_COND_SHRD); | 1847 | JUMP_COND_SHRD); |
@@ -1816,12 +1851,32 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
1816 | ctx->enckeylen, CLASS_1 | | 1851 | ctx->enckeylen, CLASS_1 | |
1817 | KEY_DEST_CLASS_REG); | 1852 | KEY_DEST_CLASS_REG); |
1818 | 1853 | ||
1854 | /* Load nonce into CONTEXT1 reg */ | ||
1855 | if (is_rfc3686) { | ||
1856 | nonce = (u32 *)(key + keylen); | ||
1857 | append_load_imm_u32(desc, *nonce, LDST_CLASS_IND_CCB | | ||
1858 | LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM); | ||
1859 | append_move(desc, MOVE_WAITCOMP | | ||
1860 | MOVE_SRC_OUTFIFO | | ||
1861 | MOVE_DEST_CLASS1CTX | | ||
1862 | (16 << MOVE_OFFSET_SHIFT) | | ||
1863 | (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT)); | ||
1864 | } | ||
1865 | |||
1819 | set_jump_tgt_here(desc, key_jump_cmd); | 1866 | set_jump_tgt_here(desc, key_jump_cmd); |
1820 | 1867 | ||
1821 | /* load IV */ | 1868 | /* load IV */ |
1822 | append_seq_load(desc, tfm->ivsize, LDST_SRCDST_BYTE_CONTEXT | | 1869 | append_seq_load(desc, crt->ivsize, LDST_SRCDST_BYTE_CONTEXT | |
1823 | LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT)); | 1870 | LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT)); |
1824 | 1871 | ||
1872 | /* Load counter into CONTEXT1 reg */ | ||
1873 | if (is_rfc3686) | ||
1874 | append_load_imm_u32(desc, be32_to_cpu(1), LDST_IMM | | ||
1875 | LDST_CLASS_1_CCB | | ||
1876 | LDST_SRCDST_BYTE_CONTEXT | | ||
1877 | ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) << | ||
1878 | LDST_OFFSET_SHIFT)); | ||
1879 | |||
1825 | /* Choose operation */ | 1880 | /* Choose operation */ |
1826 | if (ctr_mode) | 1881 | if (ctr_mode) |
1827 | append_operation(desc, ctx->class1_alg_type | | 1882 | append_operation(desc, ctx->class1_alg_type | |
@@ -3563,6 +3618,24 @@ static struct caam_alg_template driver_algs[] = { | |||
3563 | .ivsize = AES_BLOCK_SIZE, | 3618 | .ivsize = AES_BLOCK_SIZE, |
3564 | }, | 3619 | }, |
3565 | .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, | 3620 | .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, |
3621 | }, | ||
3622 | { | ||
3623 | .name = "rfc3686(ctr(aes))", | ||
3624 | .driver_name = "rfc3686-ctr-aes-caam", | ||
3625 | .blocksize = 1, | ||
3626 | .type = CRYPTO_ALG_TYPE_ABLKCIPHER, | ||
3627 | .template_ablkcipher = { | ||
3628 | .setkey = ablkcipher_setkey, | ||
3629 | .encrypt = ablkcipher_encrypt, | ||
3630 | .decrypt = ablkcipher_decrypt, | ||
3631 | .geniv = "seqiv", | ||
3632 | .min_keysize = AES_MIN_KEY_SIZE + | ||
3633 | CTR_RFC3686_NONCE_SIZE, | ||
3634 | .max_keysize = AES_MAX_KEY_SIZE + | ||
3635 | CTR_RFC3686_NONCE_SIZE, | ||
3636 | .ivsize = CTR_RFC3686_IV_SIZE, | ||
3637 | }, | ||
3638 | .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, | ||
3566 | } | 3639 | } |
3567 | }; | 3640 | }; |
3568 | 3641 | ||
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h index f227922cea38..acd7743e2603 100644 --- a/drivers/crypto/caam/compat.h +++ b/drivers/crypto/caam/compat.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <crypto/algapi.h> | 28 | #include <crypto/algapi.h> |
29 | #include <crypto/null.h> | 29 | #include <crypto/null.h> |
30 | #include <crypto/aes.h> | 30 | #include <crypto/aes.h> |
31 | #include <crypto/ctr.h> | ||
31 | #include <crypto/des.h> | 32 | #include <crypto/des.h> |
32 | #include <crypto/sha.h> | 33 | #include <crypto/sha.h> |
33 | #include <crypto/md5.h> | 34 | #include <crypto/md5.h> |