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+11)
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 if (memcmp(&ciphertext
[cao
.len
-MAC_SIZE
-1], sha1mac
, 20) != 0) {
220 fprintf(stderr
, "AEAD SHA1 MAC does not match plain MAC\n");
221 print_buf("SHA1: ", sha1mac
, 20);
222 print_buf("SHA1-TLS: ", &ciphertext
[cao
.len
-MAC_SIZE
-1], 20);
226 pad
= ciphertext
[cao
.len
-1];
229 if (ciphertext
[cao
.len
-MAC_SIZE
-1-i
] != pad
) {
230 fprintf(stderr
, "Pad does not match (expected %d)\n", pad
);
231 print_buf("PAD", &ciphertext
[cao
.len
-MAC_SIZE
-1-pad
], pad
);
235 printf("Test passed\n");
238 /* Finish crypto session */
239 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
240 perror("ioctl(CIOCFSESSION)");
250 int fd
= -1, cfd
= -1;
252 /* Open the crypto device */
253 fd
= open("/dev/crypto", O_RDWR
, 0);
255 perror("open(/dev/crypto)");
259 /* Clone file descriptor */
260 if (ioctl(fd
, CRIOGET
, &cfd
)) {
261 perror("ioctl(CRIOGET)");
265 /* Set close-on-exec (not really neede here) */
266 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
267 perror("fcntl(F_SETFD)");
271 /* Run the test itself */
273 if (test_crypto(cfd
))
276 /* Close cloned descriptor */
278 perror("close(cfd)");
282 /* Close the original descriptor */