Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: s5p-sss: Add aes-ctr support

Add support for aes counter(ctr) block cipher mode of operation for
Exynos Hardware. In contrast to ecb and cbc modes, aes-ctr allows
encyption/decryption for request sizes not being a multiple of 16(bytes).

Hardware requires block sizes being a multiple of 16(bytes). In order to
achieve this, copy request source and destination memory, and align it's size
to 16. That way hardware processes additional bytes, that are omitted
when copying the result back to its original destination.

Tested on Odroid-U3 with Exynos 4412 CPU, kernel 4.19-rc2 with crypto
run-time self test testmgr.

Signed-off-by: Christoph Manszewski <c.manszewski@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Kamil Konieczny <k.konieczny@partner.samsung.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Christoph Manszewski and committed by
Herbert Xu
cdf640a6 b1b4416f

+40 -5
+40 -5
drivers/crypto/s5p-sss.c
··· 1813 1813 }; 1814 1814 1815 1815 static void s5p_set_aes(struct s5p_aes_dev *dev, 1816 - const u8 *key, const u8 *iv, 1816 + const u8 *key, const u8 *iv, const u8 *ctr, 1817 1817 unsigned int keylen) 1818 1818 { 1819 1819 void __iomem *keystart; 1820 1820 1821 1821 if (iv) 1822 1822 memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); 1823 + 1824 + if (ctr) 1825 + memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_CNT_DATA(0), ctr, 0x10); 1823 1826 1824 1827 if (keylen == AES_KEYSIZE_256) 1825 1828 keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(0); ··· 1905 1902 u32 aes_control; 1906 1903 unsigned long flags; 1907 1904 int err; 1908 - u8 *iv; 1905 + u8 *iv, *ctr; 1909 1906 1907 + /* This sets bit [13:12] to 00, which selects 128-bit counter */ 1910 1908 aes_control = SSS_AES_KEY_CHANGE_MODE; 1911 1909 if (mode & FLAGS_AES_DECRYPT) 1912 1910 aes_control |= SSS_AES_MODE_DECRYPT; ··· 1915 1911 if ((mode & FLAGS_AES_MODE_MASK) == FLAGS_AES_CBC) { 1916 1912 aes_control |= SSS_AES_CHAIN_MODE_CBC; 1917 1913 iv = req->info; 1914 + ctr = NULL; 1918 1915 } else if ((mode & FLAGS_AES_MODE_MASK) == FLAGS_AES_CTR) { 1919 1916 aes_control |= SSS_AES_CHAIN_MODE_CTR; 1920 - iv = req->info; 1917 + iv = NULL; 1918 + ctr = req->info; 1921 1919 } else { 1922 1920 iv = NULL; /* AES_ECB */ 1921 + ctr = NULL; 1923 1922 } 1924 1923 1925 1924 if (dev->ctx->keylen == AES_KEYSIZE_192) ··· 1954 1947 goto outdata_error; 1955 1948 1956 1949 SSS_AES_WRITE(dev, AES_CONTROL, aes_control); 1957 - s5p_set_aes(dev, dev->ctx->aes_key, iv, dev->ctx->keylen); 1950 + s5p_set_aes(dev, dev->ctx->aes_key, iv, ctr, dev->ctx->keylen); 1958 1951 1959 1952 s5p_set_dma_indata(dev, dev->sg_src); 1960 1953 s5p_set_dma_outdata(dev, dev->sg_dst); ··· 2032 2025 struct s5p_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); 2033 2026 struct s5p_aes_dev *dev = ctx->dev; 2034 2027 2035 - if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { 2028 + if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE) && 2029 + ((mode & FLAGS_AES_MODE_MASK) != FLAGS_AES_CTR)) { 2036 2030 dev_err(dev->dev, "request size is not exact amount of AES blocks\n"); 2037 2031 return -EINVAL; 2038 2032 } ··· 2078 2070 static int s5p_aes_cbc_decrypt(struct ablkcipher_request *req) 2079 2071 { 2080 2072 return s5p_aes_crypt(req, FLAGS_AES_DECRYPT | FLAGS_AES_CBC); 2073 + } 2074 + 2075 + static int s5p_aes_ctr_crypt(struct ablkcipher_request *req) 2076 + { 2077 + return s5p_aes_crypt(req, FLAGS_AES_CTR); 2081 2078 } 2082 2079 2083 2080 static int s5p_aes_cra_init(struct crypto_tfm *tfm) ··· 2137 2124 .setkey = s5p_aes_setkey, 2138 2125 .encrypt = s5p_aes_cbc_encrypt, 2139 2126 .decrypt = s5p_aes_cbc_decrypt, 2127 + } 2128 + }, 2129 + { 2130 + .cra_name = "ctr(aes)", 2131 + .cra_driver_name = "ctr-aes-s5p", 2132 + .cra_priority = 100, 2133 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | 2134 + CRYPTO_ALG_ASYNC | 2135 + CRYPTO_ALG_KERN_DRIVER_ONLY, 2136 + .cra_blocksize = AES_BLOCK_SIZE, 2137 + .cra_ctxsize = sizeof(struct s5p_aes_ctx), 2138 + .cra_alignmask = 0x0f, 2139 + .cra_type = &crypto_ablkcipher_type, 2140 + .cra_module = THIS_MODULE, 2141 + .cra_init = s5p_aes_cra_init, 2142 + .cra_u.ablkcipher = { 2143 + .min_keysize = AES_MIN_KEY_SIZE, 2144 + .max_keysize = AES_MAX_KEY_SIZE, 2145 + .ivsize = AES_BLOCK_SIZE, 2146 + .setkey = s5p_aes_setkey, 2147 + .encrypt = s5p_aes_ctr_crypt, 2148 + .decrypt = s5p_aes_ctr_crypt, 2140 2149 } 2141 2150 }, 2142 2151 };