Added real usage examples, and moved test code to tests/
[cryptodev-linux.git] / tests / async_cipher.c
blobe89c7f2137f5f6756afbc9db3bfab8419956a9c6
1 /*
2 * Demo on how to use /dev/crypto device for ciphering.
4 * Placed under public domain.
6 */
7 #include <poll.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include <crypto/cryptodev.h>
16 #include "testhelper.h"
18 #define DATA_SIZE 8*1024
19 #define BLOCK_SIZE 16
20 #define KEY_SIZE 16
22 static int
23 test_crypto(int cfd)
25 char plaintext_raw[DATA_SIZE + 63], *plaintext;
26 char ciphertext_raw[DATA_SIZE + 63], *ciphertext;
27 char iv[BLOCK_SIZE];
28 char key[KEY_SIZE];
30 struct session_op sess;
31 #ifdef CIOCGSESSINFO
32 struct session_info_op siop;
33 #endif
34 struct crypt_op cryp;
36 printf("running %s\n", __func__);
38 memset(&sess, 0, sizeof(sess));
39 memset(&cryp, 0, sizeof(cryp));
41 memset(key, 0x33, sizeof(key));
42 memset(iv, 0x03, sizeof(iv));
44 /* Get crypto session for AES128 */
45 sess.cipher = CRYPTO_AES_CBC;
46 sess.keylen = KEY_SIZE;
47 sess.key = key;
48 if (ioctl(cfd, CIOCGSESSION, &sess)) {
49 perror("ioctl(CIOCGSESSION)");
50 return 1;
53 printf("%s: got the session\n", __func__);
55 #ifdef CIOCGSESSINFO
56 siop.ses = sess.ses;
57 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
58 perror("ioctl(CIOCGSESSINFO)");
59 return 1;
61 plaintext = (char *)(((unsigned long)plaintext_raw + siop.alignmask) & ~siop.alignmask);
62 ciphertext = (char *)(((unsigned long)ciphertext_raw + siop.alignmask) & ~siop.alignmask);
63 #else
64 plaintext = plaintext_raw;
65 ciphertext = ciphertext_raw;
66 #endif
67 memset(plaintext, 0x15, DATA_SIZE);
69 /* Encrypt data.in to data.encrypted */
70 cryp.ses = sess.ses;
71 cryp.len = DATA_SIZE;
72 cryp.src = plaintext;
73 cryp.dst = ciphertext;
74 cryp.iv = iv;
75 cryp.op = COP_ENCRYPT;
77 DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
78 DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
80 printf("%s: data encrypted\n", __func__);
82 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
83 perror("ioctl(CIOCFSESSION)");
84 return 1;
86 printf("%s: session finished\n", __func__);
88 if (ioctl(cfd, CIOCGSESSION, &sess)) {
89 perror("ioctl(CIOCGSESSION)");
90 return 1;
92 printf("%s: got new session\n", __func__);
94 /* Decrypt data.encrypted to data.decrypted */
95 cryp.ses = sess.ses;
96 cryp.len = DATA_SIZE;
97 cryp.src = ciphertext;
98 cryp.dst = ciphertext;
99 cryp.iv = iv;
100 cryp.op = COP_DECRYPT;
102 DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
103 DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
105 printf("%s: data encrypted\n", __func__);
107 /* Verify the result */
108 if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
109 fprintf(stderr,
110 "FAIL: Decrypted data are different from the input data.\n");
111 return 1;
112 } else
113 printf("Test passed\n");
115 /* Finish crypto session */
116 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
117 perror("ioctl(CIOCFSESSION)");
118 return 1;
121 return 0;
124 static int test_aes(int cfd)
126 char plaintext1_raw[BLOCK_SIZE + 63], *plaintext1;
127 char ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
128 char iv1[BLOCK_SIZE];
129 char key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
130 char plaintext2_data[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
131 char plaintext2_raw[BLOCK_SIZE + 63], *plaintext2;
132 char ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
133 char iv2[BLOCK_SIZE];
134 char key2[KEY_SIZE];
136 struct session_op sess1, sess2;
137 #ifdef CIOCGSESSINFO
138 struct session_info_op siop1, siop2;
139 #endif
140 struct crypt_op cryp1, cryp2;
142 memset(&sess1, 0, sizeof(sess1));
143 memset(&sess2, 0, sizeof(sess2));
144 memset(&cryp1, 0, sizeof(cryp1));
145 memset(&cryp2, 0, sizeof(cryp2));
147 /* Get crypto session for AES128 */
148 sess1.cipher = CRYPTO_AES_CBC;
149 sess1.keylen = KEY_SIZE;
150 sess1.key = key1;
151 if (ioctl(cfd, CIOCGSESSION, &sess1)) {
152 perror("ioctl(CIOCGSESSION)");
153 return 1;
155 #ifdef CIOCGSESSINFO
156 siop1.ses = sess1.ses;
157 if (ioctl(cfd, CIOCGSESSINFO, &siop1)) {
158 perror("ioctl(CIOCGSESSINFO)");
159 return 1;
161 plaintext1 = (char *)(((unsigned long)plaintext1_raw + siop1.alignmask) & ~siop1.alignmask);
162 #else
163 plaintext1 = plaintext1_raw;
164 #endif
165 memset(plaintext1, 0x0, BLOCK_SIZE);
167 memset(iv1, 0x0, sizeof(iv1));
168 memset(key2, 0x0, sizeof(key2));
170 /* Get second crypto session for AES128 */
171 sess2.cipher = CRYPTO_AES_CBC;
172 sess2.keylen = KEY_SIZE;
173 sess2.key = key2;
174 if (ioctl(cfd, CIOCGSESSION, &sess2)) {
175 perror("ioctl(CIOCGSESSION)");
176 return 1;
178 #ifdef CIOCGSESSINFO
179 siop2.ses = sess2.ses;
180 if (ioctl(cfd, CIOCGSESSINFO, &siop2)) {
181 perror("ioctl(CIOCGSESSINFO)");
182 return 1;
184 plaintext2 = (char *)(((unsigned long)plaintext2_raw + siop2.alignmask) & ~siop2.alignmask);
185 #else
186 plaintext2 = plaintext2_raw;
187 #endif
188 memcpy(plaintext2, plaintext2_data, BLOCK_SIZE);
190 /* Encrypt data.in to data.encrypted */
191 cryp1.ses = sess1.ses;
192 cryp1.len = BLOCK_SIZE;
193 cryp1.src = plaintext1;
194 cryp1.dst = plaintext1;
195 cryp1.iv = iv1;
196 cryp1.op = COP_ENCRYPT;
198 DO_OR_DIE(do_async_crypt(cfd, &cryp1), 0);
199 printf("cryp1 written out\n");
201 memset(iv2, 0x0, sizeof(iv2));
203 /* Encrypt data.in to data.encrypted */
204 cryp2.ses = sess2.ses;
205 cryp2.len = BLOCK_SIZE;
206 cryp2.src = plaintext2;
207 cryp2.dst = plaintext2;
208 cryp2.iv = iv2;
209 cryp2.op = COP_ENCRYPT;
211 DO_OR_DIE(do_async_crypt(cfd, &cryp2), 0);
212 printf("cryp2 written out\n");
214 DO_OR_DIE(do_async_fetch(cfd, &cryp1), 0);
215 DO_OR_DIE(do_async_fetch(cfd, &cryp2), 0);
216 printf("cryp1 + cryp2 successfully read\n");
218 /* Verify the result */
219 if (memcmp(plaintext1, ciphertext1, BLOCK_SIZE) != 0) {
220 int i;
221 fprintf(stderr,
222 "FAIL: Decrypted data are different from the input data.\n");
223 printf("plaintext:");
224 for (i = 0; i < BLOCK_SIZE; i++) {
225 if ((i % 30) == 0)
226 printf("\n");
227 printf("%02x ", plaintext1[i]);
229 printf("ciphertext:");
230 for (i = 0; i < BLOCK_SIZE; i++) {
231 if ((i % 30) == 0)
232 printf("\n");
233 printf("%02x ", ciphertext1[i]);
235 printf("\n");
236 return 1;
237 } else {
238 printf("result 1 passed\n");
241 /* Test 2 */
243 /* Verify the result */
244 if (memcmp(plaintext2, ciphertext2, BLOCK_SIZE) != 0) {
245 int i;
246 fprintf(stderr,
247 "FAIL: Decrypted data are different from the input data.\n");
248 printf("plaintext:");
249 for (i = 0; i < BLOCK_SIZE; i++) {
250 if ((i % 30) == 0)
251 printf("\n");
252 printf("%02x ", plaintext2[i]);
254 printf("ciphertext:");
255 for (i = 0; i < BLOCK_SIZE; i++) {
256 if ((i % 30) == 0)
257 printf("\n");
258 printf("%02x ", ciphertext2[i]);
260 printf("\n");
261 return 1;
262 } else {
263 printf("result 2 passed\n");
266 printf("AES Test passed\n");
268 /* Finish crypto session */
269 if (ioctl(cfd, CIOCFSESSION, &sess1.ses)) {
270 perror("ioctl(CIOCFSESSION)");
271 return 1;
273 if (ioctl(cfd, CIOCFSESSION, &sess2.ses)) {
274 perror("ioctl(CIOCFSESSION)");
275 return 1;
278 return 0;
282 main()
284 int fd = -1, cfd = -1;
286 /* Open the crypto device */
287 fd = open("/dev/crypto", O_RDWR, 0);
288 if (fd < 0) {
289 perror("open(/dev/crypto)");
290 return 1;
293 /* Clone file descriptor */
294 if (ioctl(fd, CRIOGET, &cfd)) {
295 perror("ioctl(CRIOGET)");
296 return 1;
299 /* Set close-on-exec (not really neede here) */
300 if (fcntl(cfd, F_SETFD, 1) == -1) {
301 perror("fcntl(F_SETFD)");
302 return 1;
305 /* Run the test itself */
306 if (test_aes(cfd))
307 return 1;
309 if (test_crypto(cfd))
310 return 1;
312 /* Close cloned descriptor */
313 if (close(cfd)) {
314 perror("close(cfd)");
315 return 1;
318 /* Close the original descriptor */
319 if (close(fd)) {
320 perror("close(fd)");
321 return 1;
324 return 0;