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)
17 #define HEADER_SIZE 193
18 #define PLAINTEXT_SIZE 1021
19 #define FOOTER_SIZE 15
23 #define MAC_SIZE 20 /* SHA1 */
28 get_sha1_hmac(int cfd
, void* key
, int key_size
, void* data
, int data_size
, void* mac
)
30 struct session_op sess
;
33 memset(&sess
, 0, sizeof(sess
));
34 memset(&cryp
, 0, sizeof(cryp
));
37 sess
.mac
= CRYPTO_SHA1_HMAC
;
38 sess
.mackeylen
= key_size
;
40 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
41 perror("ioctl(CIOCGSESSION)");
45 /* Encrypt data.in to data.encrypted */
52 cryp
.op
= COP_ENCRYPT
;
53 if (ioctl(cfd
, CIOCCRYPT
, &cryp
)) {
54 perror("ioctl(CIOCCRYPT)");
58 /* Finish crypto session */
59 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
60 perror("ioctl(CIOCFSESSION)");
67 static void print_buf(char* desc
, unsigned char* buf
, int size
)
71 for (i
=0;i
<size
;i
++) {
72 fprintf(stderr
, "%.2x", (uint8_t)buf
[i
]);
80 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
81 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
84 unsigned char sha1mac
[20];
85 unsigned char tag
[20];
86 unsigned char mackey
[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
89 struct session_op sess
;
91 struct crypt_auth_op cao
;
92 struct session_info_op siop
;
94 memset(&sess
, 0, sizeof(sess
));
95 memset(&cao
, 0, sizeof(cao
));
96 memset(&co
, 0, sizeof(co
));
98 memset(key
,0x33, sizeof(key
));
99 memset(iv
, 0x03, sizeof(iv
));
101 /* Get crypto session for AES128 */
102 sess
.cipher
= CRYPTO_AES_CTR
;
103 sess
.keylen
= KEY_SIZE
;
106 sess
.mac
= CRYPTO_SHA1_HMAC
;
107 sess
.mackeylen
= mackey_len
;
108 sess
.mackey
= mackey
;
110 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
111 perror("ioctl(CIOCGSESSION)");
116 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
117 perror("ioctl(CIOCGSESSINFO)");
122 printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
123 siop
.cipher_info
.cra_name
, siop
.cipher_info
.cra_driver_name
);
125 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
126 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
128 memset(plaintext
, 0x15, HEADER_SIZE
); /* header */
129 memset(&plaintext
[HEADER_SIZE
], 0x17, PLAINTEXT_SIZE
); /* payload */
130 memset(&plaintext
[HEADER_SIZE
+PLAINTEXT_SIZE
], 0x22, FOOTER_SIZE
);
132 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
134 /* Encrypt data.in to data.encrypted */
136 cao
.len
= PLAINTEXT_SIZE
;
137 cao
.auth_len
= HEADER_SIZE
+PLAINTEXT_SIZE
+FOOTER_SIZE
;
138 cao
.auth_src
= ciphertext
;
139 cao
.src
= ciphertext
+HEADER_SIZE
;
142 cao
.op
= COP_ENCRYPT
;
143 cao
.flags
= COP_FLAG_AEAD_SRTP_TYPE
;
147 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
148 perror("ioctl(CIOCAUTHCRYPT)");
153 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
154 perror("ioctl(CIOCFSESSION)");
158 /* Get crypto session for AES128 */
159 memset(&sess
, 0, sizeof(sess
));
160 sess
.cipher
= CRYPTO_AES_CTR
;
161 sess
.keylen
= KEY_SIZE
;
164 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
165 perror("ioctl(CIOCGSESSION)");
169 if (get_sha1_hmac(cfd
, mackey
, mackey_len
, ciphertext
, HEADER_SIZE
+ PLAINTEXT_SIZE
+ FOOTER_SIZE
, sha1mac
) != 0) {
170 fprintf(stderr
, "SHA1 MAC failed\n");
174 if (memcmp(tag
, sha1mac
, 20) != 0) {
175 fprintf(stderr
, "AEAD SHA1 MAC does not match plain MAC\n");
176 print_buf("SHA1: ", sha1mac
, 20);
177 print_buf("SHA1-SRTP: ", tag
, 20);
181 /* Decrypt data.encrypted to data.decrypted */
183 co
.len
= PLAINTEXT_SIZE
;
184 co
.src
= ciphertext
+HEADER_SIZE
;
185 co
.dst
= ciphertext
+HEADER_SIZE
;
188 if (ioctl(cfd
, CIOCCRYPT
, &co
)) {
189 perror("ioctl(CIOCCRYPT)");
193 /* Verify the result */
194 if (memcmp(plaintext
+HEADER_SIZE
, ciphertext
+HEADER_SIZE
, PLAINTEXT_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 ", (unsigned int)plaintext
[i
]);
204 printf("ciphertext:");
205 for (i
= 0; i
< DATA_SIZE
; i
++) {
208 printf("%02x ", (unsigned int)ciphertext
[i
]);
214 if (debug
) printf("Test passed\n");
216 /* Finish crypto session */
217 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
218 perror("ioctl(CIOCFSESSION)");
226 test_encrypt_decrypt(int cfd
)
228 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
229 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
232 unsigned char tag
[20];
233 unsigned char mackey
[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
236 struct session_op sess
;
237 struct crypt_auth_op cao
;
238 struct session_info_op siop
;
240 memset(&sess
, 0, sizeof(sess
));
241 memset(&cao
, 0, sizeof(cao
));
243 memset(key
,0x33, sizeof(key
));
244 memset(iv
, 0x03, sizeof(iv
));
246 /* Get crypto session for AES128 */
247 sess
.cipher
= CRYPTO_AES_CTR
;
248 sess
.keylen
= KEY_SIZE
;
251 sess
.mac
= CRYPTO_SHA1_HMAC
;
252 sess
.mackeylen
= mackey_len
;
253 sess
.mackey
= mackey
;
255 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
256 perror("ioctl(CIOCGSESSION)");
261 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
262 perror("ioctl(CIOCGSESSINFO)");
265 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
266 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
268 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
269 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
271 memset(plaintext
, 0x15, HEADER_SIZE
); /* header */
272 memset(&plaintext
[HEADER_SIZE
], 0x17, PLAINTEXT_SIZE
); /* payload */
273 memset(&plaintext
[HEADER_SIZE
+PLAINTEXT_SIZE
], 0x22, FOOTER_SIZE
);
275 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
277 /* Encrypt data.in to data.encrypted */
279 cao
.len
= PLAINTEXT_SIZE
;
280 cao
.auth_len
= HEADER_SIZE
+PLAINTEXT_SIZE
+FOOTER_SIZE
;
281 cao
.auth_src
= ciphertext
;
282 cao
.src
= ciphertext
+HEADER_SIZE
;
285 cao
.op
= COP_ENCRYPT
;
286 cao
.flags
= COP_FLAG_AEAD_SRTP_TYPE
;
290 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
291 perror("ioctl(CIOCAUTHCRYPT)");
296 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
297 perror("ioctl(CIOCFSESSION)");
301 /* Get crypto session for AES128 */
302 memset(&sess
, 0, sizeof(sess
));
303 sess
.cipher
= CRYPTO_AES_CTR
;
304 sess
.keylen
= KEY_SIZE
;
307 sess
.mac
= CRYPTO_SHA1_HMAC
;
308 sess
.mackeylen
= mackey_len
;
309 sess
.mackey
= mackey
;
311 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
312 perror("ioctl(CIOCGSESSION)");
316 /* Decrypt data.encrypted to data.decrypted */
317 /* Encrypt data.in to data.encrypted */
319 cao
.len
= PLAINTEXT_SIZE
;
320 cao
.auth_len
= HEADER_SIZE
+PLAINTEXT_SIZE
+FOOTER_SIZE
;
321 cao
.auth_src
= ciphertext
;
322 cao
.src
= ciphertext
+HEADER_SIZE
;
325 cao
.op
= COP_DECRYPT
;
326 cao
.flags
= COP_FLAG_AEAD_SRTP_TYPE
;
329 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
330 perror("ioctl(CIOCCRYPT)");
334 /* Verify the result */
335 if (memcmp(plaintext
+HEADER_SIZE
, ciphertext
+HEADER_SIZE
, PLAINTEXT_SIZE
) != 0) {
338 "FAIL: Decrypted data are different from the input data.\n");
339 printf("plaintext:");
340 for (i
= 0; i
< DATA_SIZE
; i
++) {
343 printf("%02x ", (unsigned int)plaintext
[i
]);
345 printf("ciphertext:");
346 for (i
= 0; i
< DATA_SIZE
; i
++) {
349 printf("%02x ", (unsigned int)ciphertext
[i
]);
355 if (debug
) printf("Test passed\n");
358 /* Finish crypto session */
359 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
360 perror("ioctl(CIOCFSESSION)");
368 test_encrypt_decrypt_error(int cfd
, int err
)
370 char plaintext_raw
[DATA_SIZE
+ 63], *plaintext
;
371 char ciphertext_raw
[DATA_SIZE
+ 63], *ciphertext
;
374 unsigned char tag
[20];
375 unsigned char mackey
[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
378 struct session_op sess
;
379 struct crypt_auth_op cao
;
380 struct session_info_op siop
;
382 memset(&sess
, 0, sizeof(sess
));
383 memset(&cao
, 0, sizeof(cao
));
385 memset(key
,0x33, sizeof(key
));
386 memset(iv
, 0x03, sizeof(iv
));
388 /* Get crypto session for AES128 */
389 sess
.cipher
= CRYPTO_AES_CTR
;
390 sess
.keylen
= KEY_SIZE
;
393 sess
.mac
= CRYPTO_SHA1_HMAC
;
394 sess
.mackeylen
= mackey_len
;
395 sess
.mackey
= mackey
;
397 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
398 perror("ioctl(CIOCGSESSION)");
403 if (ioctl(cfd
, CIOCGSESSINFO
, &siop
)) {
404 perror("ioctl(CIOCGSESSINFO)");
407 // printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
408 // siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
410 plaintext
= (char *)(((unsigned long)plaintext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
411 ciphertext
= (char *)(((unsigned long)ciphertext_raw
+ siop
.alignmask
) & ~siop
.alignmask
);
413 memset(plaintext
, 0x15, HEADER_SIZE
); /* header */
414 memset(&plaintext
[HEADER_SIZE
], 0x17, PLAINTEXT_SIZE
); /* payload */
415 memset(&plaintext
[HEADER_SIZE
+PLAINTEXT_SIZE
], 0x22, FOOTER_SIZE
);
417 memcpy(ciphertext
, plaintext
, DATA_SIZE
);
419 /* Encrypt data.in to data.encrypted */
421 cao
.len
= PLAINTEXT_SIZE
;
422 cao
.auth_len
= HEADER_SIZE
+PLAINTEXT_SIZE
+FOOTER_SIZE
;
423 cao
.auth_src
= ciphertext
;
424 cao
.src
= ciphertext
+HEADER_SIZE
;
427 cao
.op
= COP_ENCRYPT
;
428 cao
.flags
= COP_FLAG_AEAD_SRTP_TYPE
;
432 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
433 perror("ioctl(CIOCAUTHCRYPT)");
438 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
439 perror("ioctl(CIOCFSESSION)");
443 /* Get crypto session for AES128 */
444 memset(&sess
, 0, sizeof(sess
));
445 sess
.cipher
= CRYPTO_AES_CTR
;
446 sess
.keylen
= KEY_SIZE
;
449 sess
.mac
= CRYPTO_SHA1_HMAC
;
450 sess
.mackeylen
= mackey_len
;
451 sess
.mackey
= mackey
;
453 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
454 perror("ioctl(CIOCGSESSION)");
458 /* Decrypt data.encrypted to data.decrypted */
459 /* Encrypt data.in to data.encrypted */
463 ciphertext
[HEADER_SIZE
+3]++;
465 cao
.len
= PLAINTEXT_SIZE
;
466 cao
.auth_len
= HEADER_SIZE
+PLAINTEXT_SIZE
+FOOTER_SIZE
;
467 cao
.auth_src
= ciphertext
;
468 cao
.src
= ciphertext
+HEADER_SIZE
;
471 cao
.op
= COP_DECRYPT
;
472 cao
.flags
= COP_FLAG_AEAD_SRTP_TYPE
;
475 if (ioctl(cfd
, CIOCAUTHCRYPT
, &cao
)) {
476 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
477 perror("ioctl(CIOCFSESSION)");
481 if (debug
) printf("Test passed\n");
485 /* Verify the result */
486 if (memcmp(plaintext
+HEADER_SIZE
, ciphertext
+HEADER_SIZE
, PLAINTEXT_SIZE
) != 0) {
489 "FAIL: Decrypted data are different from the input data.\n");
490 printf("plaintext:");
491 for (i
= 0; i
< DATA_SIZE
; i
++) {
494 printf("%02x ", (unsigned int)plaintext
[i
]);
496 printf("ciphertext:");
497 for (i
= 0; i
< DATA_SIZE
; i
++) {
500 printf("%02x ", (unsigned int)ciphertext
[i
]);
506 printf("Test failed\n");
509 /* Finish crypto session */
510 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
511 perror("ioctl(CIOCFSESSION)");
519 main(int argc
, char** argv
)
521 int fd
= -1, cfd
= -1;
523 if (argc
> 1) debug
= 1;
525 /* Open the crypto device */
526 fd
= open("/dev/crypto", O_RDWR
, 0);
528 perror("open(/dev/crypto)");
532 /* Clone file descriptor */
533 if (ioctl(fd
, CRIOGET
, &cfd
)) {
534 perror("ioctl(CRIOGET)");
538 /* Set close-on-exec (not really neede here) */
539 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
540 perror("fcntl(F_SETFD)");
544 /* Run the test itself */
546 if (test_crypto(cfd
))
549 if (test_encrypt_decrypt(cfd
))
552 if (test_encrypt_decrypt_error(cfd
,0))
555 if (test_encrypt_decrypt_error(cfd
,1))
558 /* Close cloned descriptor */
560 perror("close(cfd)");
564 /* Close the original descriptor */