Added real usage examples, and moved test code to tests/
[cryptodev-linux.git] / tests / cipher.c
blob007d3fefa020896afdbc08ca3c8b240fd9f8455f
1 /*
2 * Demo on how to use /dev/crypto device for ciphering.
4 * Placed under public domain.
6 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <crypto/cryptodev.h>
15 #define DATA_SIZE 8*1024
16 #define BLOCK_SIZE 16
17 #define KEY_SIZE 16
19 static int
20 test_crypto(int cfd)
22 char plaintext_raw[DATA_SIZE + 63], *plaintext;
23 char ciphertext_raw[DATA_SIZE + 63], *ciphertext;
24 char iv[BLOCK_SIZE];
25 char key[KEY_SIZE];
27 struct session_op sess;
28 #ifdef CIOCGSESSINFO
29 struct session_info_op siop;
30 #endif
31 struct crypt_op cryp;
33 memset(&sess, 0, sizeof(sess));
34 memset(&cryp, 0, sizeof(cryp));
36 memset(key, 0x33, sizeof(key));
37 memset(iv, 0x03, sizeof(iv));
39 /* Get crypto session for AES128 */
40 sess.cipher = CRYPTO_AES_CBC;
41 sess.keylen = KEY_SIZE;
42 sess.key = key;
43 if (ioctl(cfd, CIOCGSESSION, &sess)) {
44 perror("ioctl(CIOCGSESSION)");
45 return 1;
48 #ifdef CIOCGSESSINFO
49 siop.ses = sess.ses;
50 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
51 perror("ioctl(CIOCGSESSINFO)");
52 return 1;
54 printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
55 siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
57 plaintext = (char *)(((unsigned long)plaintext_raw + siop.alignmask) & ~siop.alignmask);
58 ciphertext = (char *)(((unsigned long)ciphertext_raw + siop.alignmask) & ~siop.alignmask);
59 #else
60 plaintext = plaintext_raw;
61 ciphertext = ciphertext_raw;
62 #endif
63 memset(plaintext, 0x15, DATA_SIZE);
65 /* Encrypt data.in to data.encrypted */
66 cryp.ses = sess.ses;
67 cryp.len = DATA_SIZE;
68 cryp.src = plaintext;
69 cryp.dst = ciphertext;
70 cryp.iv = iv;
71 cryp.op = COP_ENCRYPT;
72 if (ioctl(cfd, CIOCCRYPT, &cryp)) {
73 perror("ioctl(CIOCCRYPT)");
74 return 1;
77 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
78 perror("ioctl(CIOCFSESSION)");
79 return 1;
82 if (ioctl(cfd, CIOCGSESSION, &sess)) {
83 perror("ioctl(CIOCGSESSION)");
84 return 1;
87 #ifdef CIOCGSESSINFO
88 siop.ses = sess.ses;
89 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
90 perror("ioctl(CIOCGSESSINFO)");
91 return 1;
93 printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
94 siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
95 #endif
97 /* Decrypt data.encrypted to data.decrypted */
98 cryp.ses = sess.ses;
99 cryp.len = DATA_SIZE;
100 cryp.src = ciphertext;
101 cryp.dst = ciphertext;
102 cryp.iv = iv;
103 cryp.op = COP_DECRYPT;
104 if (ioctl(cfd, CIOCCRYPT, &cryp)) {
105 perror("ioctl(CIOCCRYPT)");
106 return 1;
109 /* Verify the result */
110 if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
111 int i;
112 fprintf(stderr,
113 "FAIL: Decrypted data are different from the input data.\n");
114 printf("plaintext:");
115 for (i = 0; i < DATA_SIZE; i++) {
116 if ((i % 30) == 0)
117 printf("\n");
118 printf("%02x ", plaintext[i]);
120 printf("ciphertext:");
121 for (i = 0; i < DATA_SIZE; i++) {
122 if ((i % 30) == 0)
123 printf("\n");
124 printf("%02x ", ciphertext[i]);
126 printf("\n");
127 return 1;
128 } else
129 printf("Test passed\n");
131 /* Finish crypto session */
132 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
133 perror("ioctl(CIOCFSESSION)");
134 return 1;
137 return 0;
140 static int test_aes(int cfd)
142 char plaintext1_raw[BLOCK_SIZE + 63], *plaintext1;
143 char ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
144 char iv1[BLOCK_SIZE];
145 char key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
146 char plaintext2_data[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
147 char plaintext2_raw[BLOCK_SIZE + 63], *plaintext2;
148 char ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
149 char iv2[BLOCK_SIZE];
150 char key2[KEY_SIZE];
152 struct session_op sess;
153 #ifdef CIOCGSESSINFO
154 struct session_info_op siop;
155 #endif
156 struct crypt_op cryp;
158 memset(&sess, 0, sizeof(sess));
159 memset(&cryp, 0, sizeof(cryp));
161 /* Get crypto session for AES128 */
162 sess.cipher = CRYPTO_AES_CBC;
163 sess.keylen = KEY_SIZE;
164 sess.key = key1;
165 if (ioctl(cfd, CIOCGSESSION, &sess)) {
166 perror("ioctl(CIOCGSESSION)");
167 return 1;
169 #ifdef CIOCGSESSINFO
170 siop.ses = sess.ses;
171 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
172 perror("ioctl(CIOCGSESSINFO)");
173 return 1;
175 plaintext1 = (char *)(((unsigned long)plaintext1_raw + siop.alignmask) & ~siop.alignmask);
176 #else
177 plaintext1 = plaintext1_raw;
178 #endif
179 memset(plaintext1, 0x0, BLOCK_SIZE);
180 memset(iv1, 0x0, sizeof(iv1));
182 /* Encrypt data.in to data.encrypted */
183 cryp.ses = sess.ses;
184 cryp.len = BLOCK_SIZE;
185 cryp.src = plaintext1;
186 cryp.dst = plaintext1;
187 cryp.iv = iv1;
188 cryp.op = COP_ENCRYPT;
189 if (ioctl(cfd, CIOCCRYPT, &cryp)) {
190 perror("ioctl(CIOCCRYPT)");
191 return 1;
194 /* Verify the result */
195 if (memcmp(plaintext1, ciphertext1, BLOCK_SIZE) != 0) {
196 fprintf(stderr,
197 "FAIL: Decrypted data are different from the input data.\n");
198 return 1;
201 /* Test 2 */
203 memset(key2, 0x0, sizeof(key2));
204 memset(iv2, 0x0, sizeof(iv2));
206 /* Get crypto session for AES128 */
207 sess.cipher = CRYPTO_AES_CBC;
208 sess.keylen = KEY_SIZE;
209 sess.key = key2;
210 if (ioctl(cfd, CIOCGSESSION, &sess)) {
211 perror("ioctl(CIOCGSESSION)");
212 return 1;
215 #ifdef CIOCGSESSINFO
216 siop.ses = sess.ses;
217 if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
218 perror("ioctl(CIOCGSESSINFO)");
219 return 1;
221 printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
222 siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
224 plaintext2 = (char *)(((unsigned long)plaintext2_raw + siop.alignmask) & ~siop.alignmask);
225 #else
226 plaintext2 = plaintext2_raw;
227 #endif
228 memcpy(plaintext2, plaintext2_data, BLOCK_SIZE);
230 /* Encrypt data.in to data.encrypted */
231 cryp.ses = sess.ses;
232 cryp.len = BLOCK_SIZE;
233 cryp.src = plaintext2;
234 cryp.dst = plaintext2;
235 cryp.iv = iv2;
236 cryp.op = COP_ENCRYPT;
237 if (ioctl(cfd, CIOCCRYPT, &cryp)) {
238 perror("ioctl(CIOCCRYPT)");
239 return 1;
242 /* Verify the result */
243 if (memcmp(plaintext2, ciphertext2, BLOCK_SIZE) != 0) {
244 int i;
245 fprintf(stderr,
246 "FAIL: Decrypted data are different from the input data.\n");
247 printf("plaintext:");
248 for (i = 0; i < BLOCK_SIZE; i++) {
249 if ((i % 30) == 0)
250 printf("\n");
251 printf("%02x ", plaintext2[i]);
253 printf("ciphertext:");
254 for (i = 0; i < BLOCK_SIZE; i++) {
255 if ((i % 30) == 0)
256 printf("\n");
257 printf("%02x ", ciphertext2[i]);
259 printf("\n");
260 return 1;
263 printf("AES Test passed\n");
265 /* Finish crypto session */
266 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
267 perror("ioctl(CIOCFSESSION)");
268 return 1;
271 return 0;
275 main()
277 int fd = -1, cfd = -1;
279 /* Open the crypto device */
280 fd = open("/dev/crypto", O_RDWR, 0);
281 if (fd < 0) {
282 perror("open(/dev/crypto)");
283 return 1;
286 /* Clone file descriptor */
287 if (ioctl(fd, CRIOGET, &cfd)) {
288 perror("ioctl(CRIOGET)");
289 return 1;
292 /* Set close-on-exec (not really neede here) */
293 if (fcntl(cfd, F_SETFD, 1) == -1) {
294 perror("fcntl(F_SETFD)");
295 return 1;
298 /* Run the test itself */
299 if (test_aes(cfd))
300 return 1;
302 if (test_crypto(cfd))
303 return 1;
305 /* Close cloned descriptor */
306 if (close(cfd)) {
307 perror("close(cfd)");
308 return 1;
311 /* Close the original descriptor */
312 if (close(fd)) {
313 perror("close(fd)");
314 return 1;
317 return 0;