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
;
29 memset(&sess
, 0, sizeof(sess
));
30 memset(&cryp
, 0, sizeof(cryp
));
33 sess
.mac
= CRYPTO_SHA1_HMAC
;
34 sess
.mackeylen
= key_size
;
36 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
37 perror("ioctl(CIOCGSESSION)");
41 /* Encrypt data.in to data.encrypted */
43 cryp
.len
= data1_size
;
48 cryp
.op
= COP_ENCRYPT
;
49 cryp
.flags
= COP_FLAG_UPDATE
;
50 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
51 perror("ioctl(CIOCCRYPT)");
56 cryp
.len
= data2_size
;
61 cryp
.op
= COP_ENCRYPT
;
62 cryp
.flags
= COP_FLAG_FINAL
;
63 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
64 perror("ioctl(CIOCCRYPT)");
68 /* Finish crypto session */
69 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
70 perror("ioctl(CIOCFSESSION)");
77 static void print_buf(char* desc
, unsigned char* buf
, int size
)
81 for (i
=0;i
<size
;i
++) {
82 printf("%.2x", (uint8_t)buf
[i
]);
90 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
91 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
95 unsigned char sha1mac
[20];
98 struct session_op sess
;
100 struct crypt_auth_op cao
;
101 struct session_info_op siop
;
103 memset(&sess
, 0, sizeof(sess
));
104 memset(&cao
, 0, sizeof(cao
));
105 memset(&co
, 0, sizeof(co
));
107 memset(key
,0x33, sizeof(key
));
108 memset(iv
, 0x03, sizeof(iv
));
109 memset(auth
, 0xf1, sizeof(auth
));
111 /* Get crypto session for AES128 */
112 sess
.cipher
= CRYPTO_AES_CBC
;
113 sess
.keylen
= KEY_SIZE
;
114 sess
.key
= (void*)key
;
116 sess
.mac
= CRYPTO_SHA1_HMAC
;
118 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
120 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
121 perror("ioctl(CIOCGSESSION)");
126 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
127 perror("ioctl(CIOCGSESSINFO)");
130 printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
131 siop
.cipher_info
.cra_name
, siop
.cipher_info
.cra_driver_name
);
133 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
134 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
135 memset(plaintext
, 0x15, DATA_SIZE
);
137 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
138 fprintf(stderr
, "SHA1 MAC failed\n");
142 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
144 /* Encrypt data.in to data.encrypted */
147 cao
.auth_len
= sizeof(auth
);
149 cao
.src
= ciphertext
;
150 cao
.dst
= ciphertext
;
152 cao
.op
= COP_ENCRYPT
;
153 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
155 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
156 perror("ioctl(CIOCAUTHCRYPT)");
160 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, cao.len);
162 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
163 perror("ioctl(CIOCFSESSION)");
167 /* Get crypto session for AES128 */
168 memset(&sess
, 0, sizeof(sess
));
169 sess
.cipher
= CRYPTO_AES_CBC
;
170 sess
.keylen
= KEY_SIZE
;
173 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
174 perror("ioctl(CIOCGSESSION)");
178 /* Decrypt data.encrypted to data.decrypted */
185 if (ioctl(cfd
, CIOCCRYPT
, &co
)) {
186 perror("ioctl(CIOCCRYPT)");
190 /* Verify the result */
191 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
194 "FAIL: Decrypted data are different from the input data.\n");
195 printf("plaintext:");
196 for (i
= 0; i
< DATA_SIZE
; i
++) {
199 printf("%02x ", plaintext
[i
]);
201 printf("ciphertext:");
202 for (i
= 0; i
< DATA_SIZE
; i
++) {
205 printf("%02x ", ciphertext
[i
]);
211 pad
= ciphertext
[cao
.len
-1];
212 if (memcmp(&ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], sha1mac
, 20) != 0) {
213 fprintf(stderr
, "AEAD SHA1 MAC does not match plain MAC\n");
214 print_buf("SHA1: ", sha1mac
, 20);
215 print_buf("SHA1-TLS: ", &ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], 20);
221 if (ciphertext
[cao
.len
-1-i
] != pad
) {
222 fprintf(stderr
, "Pad does not match (expected %d)\n", pad
);
223 print_buf("PAD: ", &ciphertext
[cao
.len
-1-pad
], pad
);
227 printf("Test passed\n");
230 /* Finish crypto session */
231 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
232 perror("ioctl(CIOCFSESSION)");
240 test_encrypt_decrypt(int cfd
)
242 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
243 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
246 char auth
[AUTH_SIZE
];
247 unsigned char sha1mac
[20];
250 struct session_op sess
;
252 struct crypt_auth_op cao
;
253 struct session_info_op siop
;
255 memset(&sess
, 0, sizeof(sess
));
256 memset(&cao
, 0, sizeof(cao
));
257 memset(&co
, 0, sizeof(co
));
259 memset(key
,0x33, sizeof(key
));
260 memset(iv
, 0x03, sizeof(iv
));
261 memset(auth
, 0xf1, sizeof(auth
));
263 /* Get crypto session for AES128 */
264 sess
.cipher
= CRYPTO_AES_CBC
;
265 sess
.keylen
= KEY_SIZE
;
268 sess
.mac
= CRYPTO_SHA1_HMAC
;
270 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
272 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
273 perror("ioctl(CIOCGSESSION)");
278 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
279 perror("ioctl(CIOCGSESSINFO)");
282 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
283 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
285 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
286 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
288 memset(plaintext
, 0x15, DATA_SIZE
);
290 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
291 fprintf(stderr
, "SHA1 MAC failed\n");
295 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
297 /* Encrypt data.in to data.encrypted */
299 cao
.auth_src
= (void*)auth
;
300 cao
.auth_len
= sizeof(auth
);
302 cao
.src
= (void*)ciphertext
;
303 cao
.dst
= (void*)ciphertext
;
305 cao
.op
= COP_ENCRYPT
;
306 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
308 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
309 perror("ioctl(CIOCAUTHCRYPT)");
314 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
316 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
317 perror("ioctl(CIOCFSESSION)");
321 /* Get crypto session for AES128 */
322 memset(&sess
, 0, sizeof(sess
));
323 sess
.cipher
= CRYPTO_AES_CBC
;
324 sess
.keylen
= KEY_SIZE
;
326 sess
.mac
= CRYPTO_SHA1_HMAC
;
328 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
330 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
331 perror("ioctl(CIOCGSESSION)");
335 /* Decrypt data.encrypted to data.decrypted */
338 cao
.auth_len
= sizeof(auth
);
340 cao
.src
= ciphertext
;
341 cao
.dst
= ciphertext
;
343 cao
.op
= COP_DECRYPT
;
344 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
345 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
346 perror("ioctl(CIOCAUTHCRYPT)");
350 if (cao
.len
!= DATA_SIZE
) {
351 fprintf(stderr
, "decrypted data size incorrect!\n");
355 /* Verify the result */
356 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
359 "FAIL: Decrypted data are different from the input data.\n");
360 printf("plaintext:");
361 for (i
= 0; i
< DATA_SIZE
; i
++) {
364 printf("%02x ", plaintext
[i
]);
366 printf("ciphertext:");
367 for (i
= 0; i
< DATA_SIZE
; i
++) {
370 printf("%02x ", ciphertext
[i
]);
376 printf("Test passed\n");
379 /* Finish crypto session */
380 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
381 perror("ioctl(CIOCFSESSION)");
389 test_encrypt_decrypt_error(int cfd
, int err
)
391 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
392 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
395 char auth
[AUTH_SIZE
];
396 unsigned char sha1mac
[20];
399 struct session_op sess
;
401 struct crypt_auth_op cao
;
402 struct session_info_op siop
;
404 memset(&sess
, 0, sizeof(sess
));
405 memset(&cao
, 0, sizeof(cao
));
406 memset(&co
, 0, sizeof(co
));
408 memset(key
,0x33, sizeof(key
));
409 memset(iv
, 0x03, sizeof(iv
));
410 memset(auth
, 0xf1, sizeof(auth
));
412 /* Get crypto session for AES128 */
413 sess
.cipher
= CRYPTO_AES_CBC
;
414 sess
.keylen
= KEY_SIZE
;
417 sess
.mac
= CRYPTO_SHA1_HMAC
;
419 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
421 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
422 perror("ioctl(CIOCGSESSION)");
427 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
428 perror("ioctl(CIOCGSESSINFO)");
431 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
432 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
434 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
435 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
436 memset(plaintext
, 0x15, DATA_SIZE
);
438 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
439 fprintf(stderr
, "SHA1 MAC failed\n");
443 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
445 /* Encrypt data.in to data.encrypted */
448 cao
.auth_len
= sizeof(auth
);
450 cao
.src
= ciphertext
;
451 cao
.dst
= ciphertext
;
453 cao
.op
= COP_ENCRYPT
;
454 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
456 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
457 perror("ioctl(CIOCAUTHCRYPT)");
462 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
464 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
465 perror("ioctl(CIOCFSESSION)");
469 /* Get crypto session for AES128 */
470 memset(&sess
, 0, sizeof(sess
));
471 sess
.cipher
= CRYPTO_AES_CBC
;
472 sess
.keylen
= KEY_SIZE
;
474 sess
.mac
= CRYPTO_SHA1_HMAC
;
476 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
478 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
479 perror("ioctl(CIOCGSESSION)");
488 /* Decrypt data.encrypted to data.decrypted */
491 cao
.auth_len
= sizeof(auth
);
493 cao
.src
= ciphertext
;
494 cao
.dst
= ciphertext
;
496 cao
.op
= COP_DECRYPT
;
497 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
498 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
499 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
500 perror("ioctl(CIOCFSESSION)");
504 printf("Test passed\n");
508 /* Finish crypto session */
509 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
510 perror("ioctl(CIOCFSESSION)");
515 fprintf(stderr
, "Modification to ciphertext was not detected\n");
522 int fd
= -1, cfd
= -1;
524 /* Open the crypto device */
525 fd
= open("/dev/crypto", O_RDWR
, 0);
527 perror("open(/dev/crypto)");
531 /* Clone file descriptor */
532 if (ioctl(fd
, CRIOGET
, &cfd
)) {
533 perror("ioctl(CRIOGET)");
537 /* Set close-on-exec (not really neede here) */
538 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
539 perror("fcntl(F_SETFD)");
543 /* Run the test itself */
545 if (test_crypto(cfd
))
548 if (test_encrypt_decrypt(cfd
))
551 if (test_encrypt_decrypt_error(cfd
, 0))
554 if (test_encrypt_decrypt_error(cfd
, 1))
557 /* Close cloned descriptor */
559 perror("close(cfd)");
563 /* Close the original descriptor */