doc update
[cryptodev-linux.git] / tests / async_cipher.c
blob96ef7bc3b0a7b7e0ca90bdfb6a02dbba75c62fce
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 static int debug = 0;
20 #define DATA_SIZE 8*1024
21 #define BLOCK_SIZE 16
22 #define KEY_SIZE 16
24 static int
25 test_crypto(int cfd)
27 char plaintext_raw[DATA_SIZE + 63], *plaintext;
28 char ciphertext_raw[DATA_SIZE + 63], *ciphertext;
29 char iv[BLOCK_SIZE];
30 char key[KEY_SIZE];
32 struct session_op sess;
33 #ifdef CIOCGSESSINFO
34 struct session_info_op siop;
35 #endif
36 struct crypt_op cryp;
38 if (debug) printf("running %s\n", __func__);
40 memset(&sess, 0, sizeof(sess));
41 memset(&cryp, 0, sizeof(cryp));
43 memset(key, 0x33, sizeof(key));
44 memset(iv, 0x03, sizeof(iv));
46 /* Get crypto session for AES128 */
47 sess.cipher = CRYPTO_AES_CBC;
48 sess.keylen = KEY_SIZE;
49 sess.key = key;
50 if (ioctl(cfd, CIOCGSESSION, &sess)) {
51 perror("ioctl(CIOCGSESSION)");
52 return 1;
55 if (debug) printf("%s: got the session\n", __func__);
57 #ifdef CIOCGSESSINFO
58 siop.ses = sess.ses;
59 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
60 perror("ioctl(CIOCGSESSINFO)");
61 return 1;
63 plaintext = (char *)(((unsigned long)plaintext_raw + siop.alignmask) & ~siop.alignmask);
64 ciphertext = (char *)(((unsigned long)ciphertext_raw + siop.alignmask) & ~siop.alignmask);
65 #else
66 plaintext = plaintext_raw;
67 ciphertext = ciphertext_raw;
68 #endif
69 memset(plaintext, 0x15, DATA_SIZE);
71 /* Encrypt data.in to data.encrypted */
72 cryp.ses = sess.ses;
73 cryp.len = DATA_SIZE;
74 cryp.src = plaintext;
75 cryp.dst = ciphertext;
76 cryp.iv = iv;
77 cryp.op = COP_ENCRYPT;
79 DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
80 DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
82 if (debug) printf("%s: data encrypted\n", __func__);
84 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
85 perror("ioctl(CIOCFSESSION)");
86 return 1;
88 if (debug) printf("%s: session finished\n", __func__);
90 if (ioctl(cfd, CIOCGSESSION, &sess)) {
91 perror("ioctl(CIOCGSESSION)");
92 return 1;
94 if (debug) printf("%s: got new session\n", __func__);
96 /* Decrypt data.encrypted to data.decrypted */
97 cryp.ses = sess.ses;
98 cryp.len = DATA_SIZE;
99 cryp.src = ciphertext;
100 cryp.dst = ciphertext;
101 cryp.iv = iv;
102 cryp.op = COP_DECRYPT;
104 DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
105 DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
107 if (debug) printf("%s: data encrypted\n", __func__);
109 /* Verify the result */
110 if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
111 fprintf(stderr,
112 "FAIL: Decrypted data are different from the input data.\n");
113 return 1;
114 } else if (debug)
115 printf("Test passed\n");
117 /* Finish crypto session */
118 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
119 perror("ioctl(CIOCFSESSION)");
120 return 1;
123 return 0;
126 static int test_aes(int cfd)
128 char plaintext1_raw[BLOCK_SIZE + 63], *plaintext1;
129 char ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
130 char iv1[BLOCK_SIZE];
131 char key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
132 char plaintext2_data[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
133 char plaintext2_raw[BLOCK_SIZE + 63], *plaintext2;
134 char ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
135 char iv2[BLOCK_SIZE];
136 char key2[KEY_SIZE];
138 struct session_op sess1, sess2;
139 #ifdef CIOCGSESSINFO
140 struct session_info_op siop1, siop2;
141 #endif
142 struct crypt_op cryp1, cryp2;
144 memset(&sess1, 0, sizeof(sess1));
145 memset(&sess2, 0, sizeof(sess2));
146 memset(&cryp1, 0, sizeof(cryp1));
147 memset(&cryp2, 0, sizeof(cryp2));
149 /* Get crypto session for AES128 */
150 sess1.cipher = CRYPTO_AES_CBC;
151 sess1.keylen = KEY_SIZE;
152 sess1.key = key1;
153 if (ioctl(cfd, CIOCGSESSION, &sess1)) {
154 perror("ioctl(CIOCGSESSION)");
155 return 1;
157 #ifdef CIOCGSESSINFO
158 siop1.ses = sess1.ses;
159 if (ioctl(cfd, CIOCGSESSINFO, &siop1)) {
160 perror("ioctl(CIOCGSESSINFO)");
161 return 1;
163 plaintext1 = (char *)(((unsigned long)plaintext1_raw + siop1.alignmask) & ~siop1.alignmask);
164 #else
165 plaintext1 = plaintext1_raw;
166 #endif
167 memset(plaintext1, 0x0, BLOCK_SIZE);
169 memset(iv1, 0x0, sizeof(iv1));
170 memset(key2, 0x0, sizeof(key2));
172 /* Get second crypto session for AES128 */
173 sess2.cipher = CRYPTO_AES_CBC;
174 sess2.keylen = KEY_SIZE;
175 sess2.key = key2;
176 if (ioctl(cfd, CIOCGSESSION, &sess2)) {
177 perror("ioctl(CIOCGSESSION)");
178 return 1;
180 #ifdef CIOCGSESSINFO
181 siop2.ses = sess2.ses;
182 if (ioctl(cfd, CIOCGSESSINFO, &siop2)) {
183 perror("ioctl(CIOCGSESSINFO)");
184 return 1;
186 plaintext2 = (char *)(((unsigned long)plaintext2_raw + siop2.alignmask) & ~siop2.alignmask);
187 #else
188 plaintext2 = plaintext2_raw;
189 #endif
190 memcpy(plaintext2, plaintext2_data, BLOCK_SIZE);
192 /* Encrypt data.in to data.encrypted */
193 cryp1.ses = sess1.ses;
194 cryp1.len = BLOCK_SIZE;
195 cryp1.src = plaintext1;
196 cryp1.dst = plaintext1;
197 cryp1.iv = iv1;
198 cryp1.op = COP_ENCRYPT;
200 DO_OR_DIE(do_async_crypt(cfd, &cryp1), 0);
201 if (debug) printf("cryp1 written out\n");
203 memset(iv2, 0x0, sizeof(iv2));
205 /* Encrypt data.in to data.encrypted */
206 cryp2.ses = sess2.ses;
207 cryp2.len = BLOCK_SIZE;
208 cryp2.src = plaintext2;
209 cryp2.dst = plaintext2;
210 cryp2.iv = iv2;
211 cryp2.op = COP_ENCRYPT;
213 DO_OR_DIE(do_async_crypt(cfd, &cryp2), 0);
214 if (debug) printf("cryp2 written out\n");
216 DO_OR_DIE(do_async_fetch(cfd, &cryp1), 0);
217 DO_OR_DIE(do_async_fetch(cfd, &cryp2), 0);
218 if (debug) printf("cryp1 + cryp2 successfully read\n");
220 /* Verify the result */
221 if (memcmp(plaintext1, ciphertext1, BLOCK_SIZE) != 0) {
222 int i;
223 fprintf(stderr,
224 "FAIL: Decrypted data are different from the input data.\n");
225 printf("plaintext:");
226 for (i = 0; i < BLOCK_SIZE; i++) {
227 if ((i % 30) == 0)
228 printf("\n");
229 printf("%02x ", plaintext1[i]);
231 printf("ciphertext:");
232 for (i = 0; i < BLOCK_SIZE; i++) {
233 if ((i % 30) == 0)
234 printf("\n");
235 printf("%02x ", ciphertext1[i]);
237 printf("\n");
238 return 1;
239 } else {
240 if (debug) printf("result 1 passed\n");
243 /* Test 2 */
245 /* Verify the result */
246 if (memcmp(plaintext2, ciphertext2, BLOCK_SIZE) != 0) {
247 int i;
248 fprintf(stderr,
249 "FAIL: Decrypted data are different from the input data.\n");
250 printf("plaintext:");
251 for (i = 0; i < BLOCK_SIZE; i++) {
252 if ((i % 30) == 0)
253 printf("\n");
254 printf("%02x ", plaintext2[i]);
256 printf("ciphertext:");
257 for (i = 0; i < BLOCK_SIZE; i++) {
258 if ((i % 30) == 0)
259 printf("\n");
260 printf("%02x ", ciphertext2[i]);
262 printf("\n");
263 return 1;
264 } else {
265 if (debug) printf("result 2 passed\n");
268 if (debug) printf("AES Test passed\n");
270 /* Finish crypto session */
271 if (ioctl(cfd, CIOCFSESSION, &sess1.ses)) {
272 perror("ioctl(CIOCFSESSION)");
273 return 1;
275 if (ioctl(cfd, CIOCFSESSION, &sess2.ses)) {
276 perror("ioctl(CIOCFSESSION)");
277 return 1;
280 return 0;
284 main(int argc, char** argv)
286 int fd = -1, cfd = -1;
288 if (argc > 1) debug = 1;
290 /* Open the crypto device */
291 fd = open("/dev/crypto", O_RDWR, 0);
292 if (fd < 0) {
293 perror("open(/dev/crypto)");
294 return 1;
297 /* Clone file descriptor */
298 if (ioctl(fd, CRIOGET, &cfd)) {
299 perror("ioctl(CRIOGET)");
300 return 1;
303 /* Set close-on-exec (not really neede here) */
304 if (fcntl(cfd, F_SETFD, 1) == -1) {
305 perror("fcntl(F_SETFD)");
306 return 1;
309 /* Run the test itself */
310 if (test_aes(cfd))
311 return 1;
313 if (test_crypto(cfd))
314 return 1;
316 /* Close cloned descriptor */
317 if (close(cfd)) {
318 perror("close(cfd)");
319 return 1;
322 /* Close the original descriptor */
323 if (close(fd)) {
324 perror("close(fd)");
325 return 1;
328 return 0;