2 * Demo on how to use /dev/crypto device for ciphering.
4 * Placed under public domain.
13 #include <sys/ioctl.h>
14 #include <crypto/cryptodev.h>
16 #define DATA_SIZE (8*1024)
21 #define MAC_SIZE 20 /* SHA1 */
24 get_sha1_hmac(int cfd
, void* key
, int key_size
, void* data1
, int data1_size
, void* data2
, int data2_size
, void* mac
)
26 struct session_op sess
;
30 memset(&sess
, 0, sizeof(sess
));
31 memset(&cryp
, 0, sizeof(cryp
));
34 sess
.mac
= CRYPTO_SHA1_HMAC
;
35 sess
.mackeylen
= key_size
;
37 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
38 perror("ioctl(CIOCGSESSION)");
42 /* Encrypt data.in to data.encrypted */
44 cryp
.len
= data1_size
;
49 cryp
.op
= COP_ENCRYPT
;
50 cryp
.flags
= COP_FLAG_UPDATE
;
51 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
52 perror("ioctl(CIOCCRYPT)");
57 cryp
.len
= data2_size
;
62 cryp
.op
= COP_ENCRYPT
;
63 cryp
.flags
= COP_FLAG_FINAL
;
64 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
65 perror("ioctl(CIOCCRYPT)");
69 /* Finish crypto session */
70 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
71 perror("ioctl(CIOCFSESSION)");
78 static void print_buf(char* desc
, unsigned char* buf
, int size
)
82 for (i
=0;i
<size
;i
++) {
83 printf("%.2x", (uint8_t)buf
[i
]);
91 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
92 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
96 unsigned char sha1mac
[20];
99 struct session_op sess
;
101 struct crypt_auth_op cao
;
103 struct session_info_op siop
;
106 memset(&sess
, 0, sizeof(sess
));
107 memset(&cao
, 0, sizeof(cao
));
108 memset(&co
, 0, sizeof(co
));
110 memset(key
,0x33, sizeof(key
));
111 memset(iv
, 0x03, sizeof(iv
));
112 memset(auth
, 0xf1, sizeof(auth
));
114 /* Get crypto session for AES128 */
115 sess
.cipher
= CRYPTO_AES_CBC
;
116 sess
.keylen
= KEY_SIZE
;
119 sess
.mac
= CRYPTO_SHA1_HMAC
;
121 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
123 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
124 perror("ioctl(CIOCGSESSION)");
130 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
131 perror("ioctl(CIOCGSESSINFO)");
134 printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
135 siop
.cipher_info
.cra_name
, siop
.cipher_info
.cra_driver_name
);
137 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
138 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
140 plaintext
= plaintext_raw
;
141 ciphertext
= ciphertext_raw
;
143 memset(plaintext
, 0x15, DATA_SIZE
);
145 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
146 fprintf(stderr
, "SHA1 MAC failed\n");
150 //memcpy(ciphertext, plaintext, DATA_SIZE);
152 /* Encrypt data.in to data.encrypted */
155 cao
.auth_len
= sizeof(auth
);
158 cao
.dst
= ciphertext
;
160 cao
.op
= COP_ENCRYPT
;
161 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
163 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
164 perror("ioctl(CIOCAUTHCRYPT)");
168 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, cao.len);
170 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
171 perror("ioctl(CIOCFSESSION)");
175 /* Get crypto session for AES128 */
176 memset(&sess
, 0, sizeof(sess
));
177 sess
.cipher
= CRYPTO_AES_CBC
;
178 sess
.keylen
= KEY_SIZE
;
181 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
182 perror("ioctl(CIOCGSESSION)");
186 /* Decrypt data.encrypted to data.decrypted */
193 if (ioctl(cfd
, CIOCCRYPT
, &co
)) {
194 perror("ioctl(CIOCCRYPT)");
198 /* Verify the result */
199 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
202 "FAIL: Decrypted data are different from the input data.\n");
203 printf("plaintext:");
204 for (i
= 0; i
< DATA_SIZE
; i
++) {
207 printf("%02x ", plaintext
[i
]);
209 printf("ciphertext:");
210 for (i
= 0; i
< DATA_SIZE
; i
++) {
213 printf("%02x ", ciphertext
[i
]);
219 pad
= ciphertext
[cao
.len
-1];
220 if (memcmp(&ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], sha1mac
, 20) != 0) {
221 fprintf(stderr
, "AEAD SHA1 MAC does not match plain MAC\n");
222 print_buf("SHA1: ", sha1mac
, 20);
223 print_buf("SHA1-TLS: ", &ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], 20);
229 if (ciphertext
[cao
.len
-1-i
] != pad
) {
230 fprintf(stderr
, "Pad does not match (expected %d)\n", pad
);
231 print_buf("PAD: ", &ciphertext
[cao
.len
-1-pad
], pad
);
235 printf("Test passed\n");
238 /* Finish crypto session */
239 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
240 perror("ioctl(CIOCFSESSION)");
248 test_encrypt_decrypt(int cfd
)
250 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
251 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
254 char auth
[AUTH_SIZE
];
255 unsigned char sha1mac
[20];
258 struct session_op sess
;
260 struct crypt_auth_op cao
;
262 struct session_info_op siop
;
265 memset(&sess
, 0, sizeof(sess
));
266 memset(&cao
, 0, sizeof(cao
));
267 memset(&co
, 0, sizeof(co
));
269 memset(key
,0x33, sizeof(key
));
270 memset(iv
, 0x03, sizeof(iv
));
271 memset(auth
, 0xf1, sizeof(auth
));
273 /* Get crypto session for AES128 */
274 sess
.cipher
= CRYPTO_AES_CBC
;
275 sess
.keylen
= KEY_SIZE
;
278 sess
.mac
= CRYPTO_SHA1_HMAC
;
280 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
282 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
283 perror("ioctl(CIOCGSESSION)");
289 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
290 perror("ioctl(CIOCGSESSINFO)");
293 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
294 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
296 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
297 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
299 plaintext
= plaintext_raw
;
300 ciphertext
= ciphertext_raw
;
302 memset(plaintext
, 0x15, DATA_SIZE
);
304 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
305 fprintf(stderr
, "SHA1 MAC failed\n");
309 /* Encrypt data.in to data.encrypted */
312 cao
.auth_len
= sizeof(auth
);
315 cao
.dst
= ciphertext
;
317 cao
.op
= COP_ENCRYPT
;
318 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
320 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
321 perror("ioctl(CIOCAUTHCRYPT)");
326 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
328 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
329 perror("ioctl(CIOCFSESSION)");
333 /* Get crypto session for AES128 */
334 memset(&sess
, 0, sizeof(sess
));
335 sess
.cipher
= CRYPTO_AES_CBC
;
336 sess
.keylen
= KEY_SIZE
;
338 sess
.mac
= CRYPTO_SHA1_HMAC
;
340 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
342 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
343 perror("ioctl(CIOCGSESSION)");
347 /* Decrypt data.encrypted to data.decrypted */
350 cao
.auth_len
= sizeof(auth
);
352 cao
.src
= ciphertext
;
353 cao
.dst
= ciphertext
;
355 cao
.op
= COP_DECRYPT
;
356 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
357 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
358 perror("ioctl(CIOCAUTHCRYPT)");
362 if (cao
.len
!= DATA_SIZE
) {
363 fprintf(stderr
, "decrypted data size incorrect!\n");
367 /* Verify the result */
368 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
371 "FAIL: Decrypted data are different from the input data.\n");
372 printf("plaintext:");
373 for (i
= 0; i
< DATA_SIZE
; i
++) {
376 printf("%02x ", plaintext
[i
]);
378 printf("ciphertext:");
379 for (i
= 0; i
< DATA_SIZE
; i
++) {
382 printf("%02x ", ciphertext
[i
]);
388 printf("Test passed\n");
391 /* Finish crypto session */
392 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
393 perror("ioctl(CIOCFSESSION)");
401 test_encrypt_decrypt_error(int cfd
, int err
)
403 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
404 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
407 char auth
[AUTH_SIZE
];
408 unsigned char sha1mac
[20];
411 struct session_op sess
;
413 struct crypt_auth_op cao
;
415 struct session_info_op siop
;
418 memset(&sess
, 0, sizeof(sess
));
419 memset(&cao
, 0, sizeof(cao
));
420 memset(&co
, 0, sizeof(co
));
422 memset(key
,0x33, sizeof(key
));
423 memset(iv
, 0x03, sizeof(iv
));
424 memset(auth
, 0xf1, sizeof(auth
));
426 /* Get crypto session for AES128 */
427 sess
.cipher
= CRYPTO_AES_CBC
;
428 sess
.keylen
= KEY_SIZE
;
431 sess
.mac
= CRYPTO_SHA1_HMAC
;
433 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
435 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
436 perror("ioctl(CIOCGSESSION)");
442 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
443 perror("ioctl(CIOCGSESSINFO)");
446 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
447 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
449 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
450 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
452 plaintext
= plaintext_raw
;
453 ciphertext
= ciphertext_raw
;
455 memset(plaintext
, 0x15, DATA_SIZE
);
457 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
458 fprintf(stderr
, "SHA1 MAC failed\n");
462 /* Encrypt data.in to data.encrypted */
465 cao
.auth_len
= sizeof(auth
);
468 cao
.dst
= ciphertext
;
470 cao
.op
= COP_ENCRYPT
;
471 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
473 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
474 perror("ioctl(CIOCAUTHCRYPT)");
479 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
481 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
482 perror("ioctl(CIOCFSESSION)");
486 /* Get crypto session for AES128 */
487 memset(&sess
, 0, sizeof(sess
));
488 sess
.cipher
= CRYPTO_AES_CBC
;
489 sess
.keylen
= KEY_SIZE
;
491 sess
.mac
= CRYPTO_SHA1_HMAC
;
493 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
495 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
496 perror("ioctl(CIOCGSESSION)");
505 /* Decrypt data.encrypted to data.decrypted */
508 cao
.auth_len
= sizeof(auth
);
510 cao
.src
= ciphertext
;
511 cao
.dst
= ciphertext
;
513 cao
.op
= COP_DECRYPT
;
514 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
515 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
516 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
517 perror("ioctl(CIOCFSESSION)");
521 printf("Test passed\n");
525 /* Finish crypto session */
526 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
527 perror("ioctl(CIOCFSESSION)");
532 fprintf(stderr
, "Modification to ciphertext was not detected\n");
539 int fd
= -1, cfd
= -1;
541 /* Open the crypto device */
542 fd
= open("/dev/crypto", O_RDWR
, 0);
544 perror("open(/dev/crypto)");
548 /* Clone file descriptor */
549 if (ioctl(fd
, CRIOGET
, &cfd
)) {
550 perror("ioctl(CRIOGET)");
554 /* Set close-on-exec (not really neede here) */
555 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
556 perror("fcntl(F_SETFD)");
560 /* Run the test itself */
562 if (test_crypto(cfd
))
565 if (test_encrypt_decrypt(cfd
))
568 if (test_encrypt_decrypt_error(cfd
, 0))
571 if (test_encrypt_decrypt_error(cfd
, 1))
574 /* Close cloned descriptor */
576 perror("close(cfd)");
580 /* Close the original descriptor */