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 */
26 get_sha1_hmac(int cfd
, void* key
, int key_size
, void* data1
, int data1_size
, void* data2
, int data2_size
, void* mac
)
28 struct session_op sess
;
31 memset(&sess
, 0, sizeof(sess
));
32 memset(&cryp
, 0, sizeof(cryp
));
35 sess
.mac
= CRYPTO_SHA1_HMAC
;
36 sess
.mackeylen
= key_size
;
38 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
39 perror("ioctl(CIOCGSESSION)");
43 /* Encrypt data.in to data.encrypted */
45 cryp
.len
= data1_size
;
50 cryp
.op
= COP_ENCRYPT
;
51 cryp
.flags
= COP_FLAG_UPDATE
;
52 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
53 perror("ioctl(CIOCCRYPT)");
58 cryp
.len
= data2_size
;
63 cryp
.op
= COP_ENCRYPT
;
64 cryp
.flags
= COP_FLAG_FINAL
;
65 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
66 perror("ioctl(CIOCCRYPT)");
70 /* Finish crypto session */
71 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
72 perror("ioctl(CIOCFSESSION)");
79 static void print_buf(char* desc
, unsigned char* buf
, int size
)
83 for (i
=0;i
<size
;i
++) {
84 printf("%.2x", (uint8_t)buf
[i
]);
92 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
93 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
97 unsigned char sha1mac
[20];
100 struct session_op sess
;
102 struct crypt_auth_op cao
;
103 struct session_info_op siop
;
105 memset(&sess
, 0, sizeof(sess
));
106 memset(&cao
, 0, sizeof(cao
));
107 memset(&co
, 0, sizeof(co
));
109 memset(key
,0x33, sizeof(key
));
110 memset(iv
, 0x03, sizeof(iv
));
111 memset(auth
, 0xf1, sizeof(auth
));
113 /* Get crypto session for AES128 */
114 sess
.cipher
= CRYPTO_AES_CBC
;
115 sess
.keylen
= KEY_SIZE
;
116 sess
.key
= (void*)key
;
118 sess
.mac
= CRYPTO_SHA1_HMAC
;
120 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
122 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
123 perror("ioctl(CIOCGSESSION)");
128 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
129 perror("ioctl(CIOCGSESSINFO)");
133 printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
134 siop
.cipher_info
.cra_name
, siop
.cipher_info
.cra_driver_name
);
136 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
137 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
138 memset(plaintext
, 0x15, DATA_SIZE
);
140 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
141 fprintf(stderr
, "SHA1 MAC failed\n");
145 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
147 /* Encrypt data.in to data.encrypted */
150 cao
.auth_len
= sizeof(auth
);
152 cao
.src
= ciphertext
;
153 cao
.dst
= ciphertext
;
155 cao
.op
= COP_ENCRYPT
;
156 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
158 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
159 perror("ioctl(CIOCAUTHCRYPT)");
163 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, cao.len);
165 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
166 perror("ioctl(CIOCFSESSION)");
170 /* Get crypto session for AES128 */
171 memset(&sess
, 0, sizeof(sess
));
172 sess
.cipher
= CRYPTO_AES_CBC
;
173 sess
.keylen
= KEY_SIZE
;
176 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
177 perror("ioctl(CIOCGSESSION)");
181 /* Decrypt data.encrypted to data.decrypted */
188 if (ioctl(cfd
, CIOCCRYPT
, &co
)) {
189 perror("ioctl(CIOCCRYPT)");
193 /* Verify the result */
194 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
197 "FAIL: Decrypted data are different from the input data.\n");
198 printf("plaintext:");
199 for (i
= 0; i
< DATA_SIZE
; i
++) {
202 printf("%02x ", plaintext
[i
]);
204 printf("ciphertext:");
205 for (i
= 0; i
< DATA_SIZE
; i
++) {
208 printf("%02x ", ciphertext
[i
]);
214 pad
= ciphertext
[cao
.len
-1];
215 if (memcmp(&ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], sha1mac
, 20) != 0) {
216 fprintf(stderr
, "AEAD SHA1 MAC does not match plain MAC\n");
217 print_buf("SHA1: ", sha1mac
, 20);
218 print_buf("SHA1-TLS: ", &ciphertext
[cao
.len
-MAC_SIZE
-pad
-1], 20);
224 if (ciphertext
[cao
.len
-1-i
] != pad
) {
225 fprintf(stderr
, "Pad does not match (expected %d)\n", pad
);
226 print_buf("PAD: ", &ciphertext
[cao
.len
-1-pad
], pad
);
230 if (debug
) printf("Test passed\n");
233 /* Finish crypto session */
234 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
235 perror("ioctl(CIOCFSESSION)");
243 test_encrypt_decrypt(int cfd
)
245 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
246 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
249 char auth
[AUTH_SIZE
];
250 unsigned char sha1mac
[20];
253 struct session_op sess
;
255 struct crypt_auth_op cao
;
256 struct session_info_op siop
;
258 memset(&sess
, 0, sizeof(sess
));
259 memset(&cao
, 0, sizeof(cao
));
260 memset(&co
, 0, sizeof(co
));
262 memset(key
,0x33, sizeof(key
));
263 memset(iv
, 0x03, sizeof(iv
));
264 memset(auth
, 0xf1, sizeof(auth
));
266 /* Get crypto session for AES128 */
267 sess
.cipher
= CRYPTO_AES_CBC
;
268 sess
.keylen
= KEY_SIZE
;
271 sess
.mac
= CRYPTO_SHA1_HMAC
;
273 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
275 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
276 perror("ioctl(CIOCGSESSION)");
281 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
282 perror("ioctl(CIOCGSESSINFO)");
285 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
286 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
288 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
289 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
291 memset(plaintext
, 0x15, DATA_SIZE
);
293 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
294 fprintf(stderr
, "SHA1 MAC failed\n");
298 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
300 /* Encrypt data.in to data.encrypted */
302 cao
.auth_src
= (void*)auth
;
303 cao
.auth_len
= sizeof(auth
);
305 cao
.src
= (void*)ciphertext
;
306 cao
.dst
= (void*)ciphertext
;
308 cao
.op
= COP_ENCRYPT
;
309 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
311 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
312 perror("ioctl(CIOCAUTHCRYPT)");
317 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
319 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
320 perror("ioctl(CIOCFSESSION)");
324 /* Get crypto session for AES128 */
325 memset(&sess
, 0, sizeof(sess
));
326 sess
.cipher
= CRYPTO_AES_CBC
;
327 sess
.keylen
= KEY_SIZE
;
329 sess
.mac
= CRYPTO_SHA1_HMAC
;
331 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
333 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
334 perror("ioctl(CIOCGSESSION)");
338 /* Decrypt data.encrypted to data.decrypted */
341 cao
.auth_len
= sizeof(auth
);
343 cao
.src
= ciphertext
;
344 cao
.dst
= ciphertext
;
346 cao
.op
= COP_DECRYPT
;
347 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
348 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
349 perror("ioctl(CIOCAUTHCRYPT)");
353 if (cao
.len
!= DATA_SIZE
) {
354 fprintf(stderr
, "decrypted data size incorrect!\n");
358 /* Verify the result */
359 if (memcmp(plaintext
, ciphertext
, DATA_SIZE
) != 0) {
362 "FAIL: Decrypted data are different from the input data.\n");
363 printf("plaintext:");
364 for (i
= 0; i
< DATA_SIZE
; i
++) {
367 printf("%02x ", plaintext
[i
]);
369 printf("ciphertext:");
370 for (i
= 0; i
< DATA_SIZE
; i
++) {
373 printf("%02x ", ciphertext
[i
]);
379 if (debug
) printf("Test passed\n");
382 /* Finish crypto session */
383 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
384 perror("ioctl(CIOCFSESSION)");
392 test_encrypt_decrypt_error(int cfd
, int err
)
394 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
395 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
398 char auth
[AUTH_SIZE
];
399 unsigned char sha1mac
[20];
402 struct session_op sess
;
404 struct crypt_auth_op cao
;
405 struct session_info_op siop
;
407 memset(&sess
, 0, sizeof(sess
));
408 memset(&cao
, 0, sizeof(cao
));
409 memset(&co
, 0, sizeof(co
));
411 memset(key
,0x33, sizeof(key
));
412 memset(iv
, 0x03, sizeof(iv
));
413 memset(auth
, 0xf1, sizeof(auth
));
415 /* Get crypto session for AES128 */
416 sess
.cipher
= CRYPTO_AES_CBC
;
417 sess
.keylen
= KEY_SIZE
;
420 sess
.mac
= CRYPTO_SHA1_HMAC
;
422 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
424 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
425 perror("ioctl(CIOCGSESSION)");
430 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
431 perror("ioctl(CIOCGSESSINFO)");
434 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
435 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
437 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
438 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
439 memset(plaintext
, 0x15, DATA_SIZE
);
441 if (get_sha1_hmac(cfd
, sess
.mackey
, sess
.mackeylen
, auth
, sizeof(auth
), plaintext
, DATA_SIZE
, sha1mac
) != 0) {
442 fprintf(stderr
, "SHA1 MAC failed\n");
446 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
448 /* Encrypt data.in to data.encrypted */
451 cao
.auth_len
= sizeof(auth
);
453 cao
.src
= ciphertext
;
454 cao
.dst
= ciphertext
;
456 cao
.op
= COP_ENCRYPT
;
457 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
459 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
460 perror("ioctl(CIOCAUTHCRYPT)");
465 //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
467 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
468 perror("ioctl(CIOCFSESSION)");
472 /* Get crypto session for AES128 */
473 memset(&sess
, 0, sizeof(sess
));
474 sess
.cipher
= CRYPTO_AES_CBC
;
475 sess
.keylen
= KEY_SIZE
;
477 sess
.mac
= CRYPTO_SHA1_HMAC
;
479 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
481 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
482 perror("ioctl(CIOCGSESSION)");
491 /* Decrypt data.encrypted to data.decrypted */
494 cao
.auth_len
= sizeof(auth
);
496 cao
.src
= ciphertext
;
497 cao
.dst
= ciphertext
;
499 cao
.op
= COP_DECRYPT
;
500 cao
.flags
= COP_FLAG_AEAD_TLS_TYPE
;
501 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
502 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
503 perror("ioctl(CIOCFSESSION)");
507 if (debug
) printf("Test passed\n");
511 /* Finish crypto session */
512 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
513 perror("ioctl(CIOCFSESSION)");
518 fprintf(stderr
, "Modification to ciphertext was not detected\n");
525 int fd
= -1, cfd
= -1;
527 /* Open the crypto device */
528 fd
= open("/dev/crypto", O_RDWR
, 0);
530 perror("open(/dev/crypto)");
534 /* Clone file descriptor */
535 if (ioctl(fd
, CRIOGET
, &cfd
)) {
536 perror("ioctl(CRIOGET)");
540 /* Set close-on-exec (not really neede here) */
541 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
542 perror("fcntl(F_SETFD)");
546 /* Run the test itself */
548 if (test_crypto(cfd
))
551 if (test_encrypt_decrypt(cfd
))
554 if (test_encrypt_decrypt_error(cfd
, 0))
557 if (test_encrypt_decrypt_error(cfd
, 1))
560 /* Close cloned descriptor */
562 perror("close(cfd)");
566 /* Close the original descriptor */