Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * sun4i-ss.h - hardware cryptographic accelerator for Allwinner A20 SoC * * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com> * * Support AES cipher with 128,192,256 bits keysize. * Support MD5 and SHA1 hash algorithms. * Support DES and 3DES * * You could find the datasheet in Documentation/arm/sunxi.rst */ #include <linux/clk.h> #include <linux/crypto.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/reset.h> #include <crypto/scatterwalk.h> #include <linux/scatterlist.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/pm_runtime.h> #include <crypto/md5.h> #include <crypto/skcipher.h> #include <crypto/sha1.h> #include <crypto/hash.h> #include <crypto/internal/hash.h> #include <crypto/internal/skcipher.h> #include <crypto/aes.h> #include <crypto/internal/des.h> #include <crypto/internal/rng.h> #include <crypto/rng.h> #define SS_CTL 0x00 #define SS_KEY0 0x04 #define SS_KEY1 0x08 #define SS_KEY2 0x0C #define SS_KEY3 0x10 #define SS_KEY4 0x14 #define SS_KEY5 0x18 #define SS_KEY6 0x1C #define SS_KEY7 0x20 #define SS_IV0 0x24 #define SS_IV1 0x28 #define SS_IV2 0x2C #define SS_IV3 0x30 #define SS_FCSR 0x44 #define SS_MD0 0x4C #define SS_MD1 0x50 #define SS_MD2 0x54 #define SS_MD3 0x58 #define SS_MD4 0x5C #define SS_RXFIFO 0x200 #define SS_TXFIFO 0x204 /* SS_CTL configuration values */ /* PRNG generator mode - bit 15 */ #define SS_PRNG_ONESHOT (0 << 15) #define SS_PRNG_CONTINUE (1 << 15) /* IV mode for hash */ #define SS_IV_ARBITRARY (1 << 14) /* SS operation mode - bits 12-13 */ #define SS_ECB (0 << 12) #define SS_CBC (1 << 12) #define SS_CTS (3 << 12) /* Counter width for CNT mode - bits 10-11 */ #define SS_CNT_16BITS (0 << 10) #define SS_CNT_32BITS (1 << 10) #define SS_CNT_64BITS (2 << 10) /* Key size for AES - bits 8-9 */ #define SS_AES_128BITS (0 << 8) #define SS_AES_192BITS (1 << 8) #define SS_AES_256BITS (2 << 8) /* Operation direction - bit 7 */ #define SS_ENCRYPTION (0 << 7) #define SS_DECRYPTION (1 << 7) /* SS Method - bits 4-6 */ #define SS_OP_AES (0 << 4) #define SS_OP_DES (1 << 4) #define SS_OP_3DES (2 << 4) #define SS_OP_SHA1 (3 << 4) #define SS_OP_MD5 (4 << 4) #define SS_OP_PRNG (5 << 4) /* Data end bit - bit 2 */ #define SS_DATA_END (1 << 2) /* PRNG start bit - bit 1 */ #define SS_PRNG_START (1 << 1) /* SS Enable bit - bit 0 */ #define SS_DISABLED (0 << 0) #define SS_ENABLED (1 << 0) /* SS_FCSR configuration values */ /* RX FIFO status - bit 30 */ #define SS_RXFIFO_FREE (1 << 30) /* RX FIFO empty spaces - bits 24-29 */ #define SS_RXFIFO_SPACES(val) (((val) >> 24) & 0x3f) /* TX FIFO status - bit 22 */ #define SS_TXFIFO_AVAILABLE (1 << 22) /* TX FIFO available spaces - bits 16-21 */ #define SS_TXFIFO_SPACES(val) (((val) >> 16) & 0x3f) #define SS_RX_MAX 32 #define SS_RX_DEFAULT SS_RX_MAX #define SS_TX_MAX 33 #define SS_RXFIFO_EMP_INT_PENDING (1 << 10) #define SS_TXFIFO_AVA_INT_PENDING (1 << 8) #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) #define SS_SEED_LEN 192 #define SS_DATA_LEN 160 /* * struct ss_variant - Describe SS hardware variant * @sha1_in_be: The SHA1 digest is given by SS in BE, and so need to be inverted. */ struct ss_variant { bool sha1_in_be; }; struct sun4i_ss_ctx { const struct ss_variant *variant; void __iomem *base; int irq; struct clk *busclk; struct clk *ssclk; struct reset_control *reset; struct device *dev; struct resource *res; char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ spinlock_t slock; /* control the use of the device */ #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG u32 seed[SS_SEED_LEN / BITS_PER_LONG]; #endif struct dentry *dbgfs_dir; struct dentry *dbgfs_stats; }; struct sun4i_ss_alg_template { u32 type; u32 mode; union { struct skcipher_alg crypto; struct ahash_alg hash; struct rng_alg rng; } alg; struct sun4i_ss_ctx *ss; unsigned long stat_req; unsigned long stat_fb; unsigned long stat_bytes; unsigned long stat_opti; }; struct sun4i_tfm_ctx { u32 key[AES_MAX_KEY_SIZE / 4];/* divided by sizeof(u32) */ u32 keylen; u32 keymode; struct sun4i_ss_ctx *ss; struct crypto_skcipher *fallback_tfm; }; struct sun4i_cipher_req_ctx { u32 mode; u8 backup_iv[AES_BLOCK_SIZE]; struct skcipher_request fallback_req; // keep at the end }; struct sun4i_req_ctx { u32 mode; u64 byte_count; /* number of bytes "uploaded" to the device */ u32 hash[5]; /* for storing SS_IVx register */ char buf[64]; unsigned int len; int flags; }; int sun4i_hash_crainit(struct crypto_tfm *tfm); void sun4i_hash_craexit(struct crypto_tfm *tfm); int sun4i_hash_init(struct ahash_request *areq); int sun4i_hash_update(struct ahash_request *areq); int sun4i_hash_final(struct ahash_request *areq); int sun4i_hash_finup(struct ahash_request *areq); int sun4i_hash_digest(struct ahash_request *areq); int sun4i_hash_export_md5(struct ahash_request *areq, void *out); int sun4i_hash_import_md5(struct ahash_request *areq, const void *in); int sun4i_hash_export_sha1(struct ahash_request *areq, void *out); int sun4i_hash_import_sha1(struct ahash_request *areq, const void *in); int sun4i_ss_cbc_aes_encrypt(struct skcipher_request *areq); int sun4i_ss_cbc_aes_decrypt(struct skcipher_request *areq); int sun4i_ss_ecb_aes_encrypt(struct skcipher_request *areq); int sun4i_ss_ecb_aes_decrypt(struct skcipher_request *areq); int sun4i_ss_cbc_des_encrypt(struct skcipher_request *areq); int sun4i_ss_cbc_des_decrypt(struct skcipher_request *areq); int sun4i_ss_ecb_des_encrypt(struct skcipher_request *areq); int sun4i_ss_ecb_des_decrypt(struct skcipher_request *areq); int sun4i_ss_cbc_des3_encrypt(struct skcipher_request *areq); int sun4i_ss_cbc_des3_decrypt(struct skcipher_request *areq); int sun4i_ss_ecb_des3_encrypt(struct skcipher_request *areq); int sun4i_ss_ecb_des3_decrypt(struct skcipher_request *areq); int sun4i_ss_cipher_init(struct crypto_tfm *tfm); void sun4i_ss_cipher_exit(struct crypto_tfm *tfm); int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int dlen); int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); |