aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-cris/arch-v32/cryptocop.h
blob: dfa1f66fb987310726fa1ffbcc5e9edac324b223 (plain) (blame)
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
 * The device /dev/cryptocop is accessible using this driver using
 * CRYPTOCOP_MAJOR (254) and minor number 0.
 */

#ifndef CRYPTOCOP_H
#define CRYPTOCOP_H

#include <linux/uio.h>


#define CRYPTOCOP_SESSION_ID_NONE (0)

typedef unsigned long long int cryptocop_session_id;

/* cryptocop ioctls */
#define ETRAXCRYPTOCOP_IOCTYPE         (250)

#define CRYPTOCOP_IO_CREATE_SESSION    _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 1, struct strcop_session_op)
#define CRYPTOCOP_IO_CLOSE_SESSION     _IOW(ETRAXCRYPTOCOP_IOCTYPE, 2, struct strcop_session_op)
#define CRYPTOCOP_IO_PROCESS_OP        _IOWR(ETRAXCRYPTOCOP_IOCTYPE, 3, struct strcop_crypto_op)
#define CRYPTOCOP_IO_MAXNR             (3)

typedef enum {
	cryptocop_cipher_des = 0,
	cryptocop_cipher_3des = 1,
	cryptocop_cipher_aes = 2,
	cryptocop_cipher_m2m = 3, /* mem2mem is essentially a NULL cipher with blocklength=1 */
	cryptocop_cipher_none
} cryptocop_cipher_type;

typedef enum {
	cryptocop_digest_sha1 = 0,
	cryptocop_digest_md5 = 1,
	cryptocop_digest_none
} cryptocop_digest_type;

typedef enum {
	cryptocop_csum_le = 0,
	cryptocop_csum_be = 1,
	cryptocop_csum_none
} cryptocop_csum_type;

typedef enum {
	cryptocop_cipher_mode_ecb = 0,
	cryptocop_cipher_mode_cbc,
	cryptocop_cipher_mode_none
} cryptocop_cipher_mode;

typedef enum {
	cryptocop_3des_eee = 0,
	cryptocop_3des_eed = 1,
	cryptocop_3des_ede = 2,
	cryptocop_3des_edd = 3,
	cryptocop_3des_dee = 4,
	cryptocop_3des_ded = 5,
	cryptocop_3des_dde = 6,
	cryptocop_3des_ddd = 7
} cryptocop_3des_mode;

/* Usermode accessible (ioctl) operations. */
struct strcop_session_op{
	cryptocop_session_id    ses_id;

	cryptocop_cipher_type   cipher; /* AES, DES, 3DES, m2m, none */

	cryptocop_cipher_mode   cmode; /* ECB, CBC, none */
	cryptocop_3des_mode     des3_mode;

	cryptocop_digest_type   digest; /* MD5, SHA1, none */

	cryptocop_csum_type     csum;   /* BE, LE, none */

	unsigned char           *key;
	size_t                  keylen;
};

#define CRYPTOCOP_CSUM_LENGTH         (2)
#define CRYPTOCOP_MAX_DIGEST_LENGTH   (20)  /* SHA-1 20, MD5 16 */
#define CRYPTOCOP_MAX_IV_LENGTH       (16)  /* (3)DES==8, AES == 16 */
#define CRYPTOCOP_MAX_KEY_LENGTH      (32)

struct strcop_crypto_op{
	cryptocop_session_id ses_id;

	/* Indata. */
	unsigned char            *indata;
	size_t                   inlen; /* Total indata length. */

	/* Cipher configuration. */
	unsigned char            do_cipher:1;
	unsigned char            decrypt:1; /* 1 == decrypt, 0 == encrypt */
	unsigned char            cipher_explicit:1;
	size_t                   cipher_start;
	size_t                   cipher_len;
	/* cipher_iv is used if do_cipher and cipher_explicit and the cipher
	   mode is CBC.  The length is controlled by the type of cipher,
	   e.g. DES/3DES 8 octets and AES 16 octets. */
	unsigned char            cipher_iv[CRYPTOCOP_MAX_IV_LENGTH];
	/* Outdata. */
	unsigned char            *cipher_outdata;
	size_t                   cipher_outlen;

	/* digest configuration. */
	unsigned char            do_digest:1;
	size_t                   digest_start;
	size_t                   digest_len;
	/* Outdata.  The actual length is determined by the type of the digest. */
	unsigned char            digest[CRYPTOCOP_MAX_DIGEST_LENGTH];

	/* Checksum configuration. */
	unsigned char            do_csum:1;
	size_t                   csum_start;
	size_t                   csum_len;
	/* Outdata. */
	unsigned char            csum[CRYPTOCOP_CSUM_LENGTH];
};



#ifdef __KERNEL__

/********** The API to use from inside the kernel. ************/

#include <asm/arch/hwregs/dma.h>

typedef enum {
	cryptocop_alg_csum = 0,
	cryptocop_alg_mem2mem,
	cryptocop_alg_md5,
	cryptocop_alg_sha1,
	cryptocop_alg_des,
	cryptocop_alg_3des,
	cryptocop_alg_aes,
	cryptocop_no_alg,
} cryptocop_algorithm;

typedef u8 cryptocop_tfrm_id;


struct cryptocop_operation;

typedef void (cryptocop_callback)(struct cryptocop_operation*, void*);

struct cryptocop_transform_init {
	cryptocop_algorithm    alg;
	/* Keydata for ciphers. */
	unsigned char          key[CRYPTOCOP_MAX_KEY_LENGTH];
	unsigned int           keylen;
	cryptocop_cipher_mode  cipher_mode;
	cryptocop_3des_mode    tdes_mode;
	cryptocop_csum_type    csum_mode; /* cryptocop_csum_none is not allowed when alg==cryptocop_alg_csum */

	cryptocop_tfrm_id tid; /* Locally unique in session; assigned by user, checked by driver. */
	struct cryptocop_transform_init *next;
};


typedef enum {
	cryptocop_source_dma = 0,
	cryptocop_source_des,
	cryptocop_source_3des,
	cryptocop_source_aes,
	cryptocop_source_md5,
	cryptocop_source_sha1,
	cryptocop_source_csum,
	cryptocop_source_none,
} cryptocop_source;


struct cryptocop_desc_cfg {
	cryptocop_tfrm_id tid;
	cryptocop_source src;
	unsigned int last:1; /* Last use of this transform in the operation.  Will push outdata when encountered. */
	struct cryptocop_desc_cfg *next;
};

struct cryptocop_desc {
	size_t length;
	struct cryptocop_desc_cfg *cfg;
	struct cryptocop_desc *next;
};


/* Flags for cryptocop_tfrm_cfg */
#define CRYPTOCOP_NO_FLAG     (0x00)
#define CRYPTOCOP_ENCRYPT     (0x01)
#define CRYPTOCOP_DECRYPT     (0x02)
#define CRYPTOCOP_EXPLICIT_IV (0x04)

struct cryptocop_tfrm_cfg {
	cryptocop_tfrm_id tid;

	unsigned int flags; /* DECRYPT, ENCRYPT, EXPLICIT_IV */

	/* CBC initialisation vector for cihers. */
	u8 iv[CRYPTOCOP_MAX_IV_LENGTH];

	/* The position in output where to write the transform output.  The order
	   in which the driver writes the output is unspecified, hence if several
	   transforms write on the same positions in the output the result is
	   unspecified. */
	size_t inject_ix;

	struct cryptocop_tfrm_cfg *next;
};



struct cryptocop_dma_list_operation{
	/* The consumer can provide DMA lists to send to the co-processor.  'use_dmalists' in
	   struct cryptocop_operation must be set for the driver to use them.  outlist,
	   out_data_buf, inlist and in_data_buf must all be physical addresses since they will
	   be loaded to DMA . */
	dma_descr_data *outlist; /* Out from memory to the co-processor. */
	char           *out_data_buf;
	dma_descr_data *inlist; /* In from the co-processor to memory. */
	char           *in_data_buf;

	cryptocop_3des_mode tdes_mode;
	cryptocop_csum_type csum_mode;
};


struct cryptocop_tfrm_operation{
	/* Operation configuration, if not 'use_dmalists' is set. */
	struct cryptocop_tfrm_cfg *tfrm_cfg;
	struct cryptocop_desc *desc;

	struct iovec *indata;
	size_t incount;
	size_t inlen; /* Total inlength. */

	struct iovec *outdata;
	size_t outcount;
	size_t outlen; /* Total outlength. */
};


struct cryptocop_operation {
	cryptocop_callback *cb;
	void *cb_data;

	cryptocop_session_id sid;

	/* The status of the operation when returned to consumer. */
	int operation_status; /* 0, -EAGAIN */

	/* Flags */
	unsigned int use_dmalists:1;  /* Use outlist and inlist instead of the desc/tfrm_cfg configuration. */
	unsigned int in_interrupt:1;  /* Set if inserting job from interrupt context. */
	unsigned int fast_callback:1; /* Set if fast callback wanted, i.e. from interrupt context. */

	union{
		struct cryptocop_dma_list_operation list_op;
		struct cryptocop_tfrm_operation tfrm_op;
	};
};


int cryptocop_new_session(cryptocop_session_id *sid, struct cryptocop_transform_init *tinit, int alloc_flag);
int cryptocop_free_session(cryptocop_session_id sid);

int cryptocop_job_queue_insert_csum(struct cryptocop_operation *operation);

int cryptocop_job_queue_insert_crypto(struct cryptocop_operation *operation);

int cryptocop_job_queue_insert_user_job(struct cryptocop_operation *operation);

#endif /* __KERNEL__ */

#endif /* CRYPTOCOP_H */