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/arch/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);
|