2 * Demo on how to use /dev/crypto device for HMAC.
4 * Placed under public domain.
14 #include <sys/ioctl.h>
15 #include <crypto/cryptodev.h>
17 #include "testhelper.h"
21 #define DATA_SIZE 4096
24 #define SHA1_HASH_LEN 20
30 uint8_t in
[DATA_SIZE
],
36 struct session_op sess
;
38 uint8_t mac
[AALG_MAX_RESULT_LEN
];
39 uint8_t oldmac
[AALG_MAX_RESULT_LEN
];
40 uint8_t md5_hmac_out
[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
41 uint8_t sha1_out
[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
44 memset(&sess
, 0, sizeof(sess
));
45 memset(&cryp
, 0, sizeof(cryp
));
47 /* Use the garbage that is on the stack :-) */
48 /* memset(&data, 0, sizeof(data)); */
51 memset(mac
, 0, sizeof(mac
));
54 sess
.mac
= CRYPTO_SHA1
;
55 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
56 perror("ioctl(CIOCGSESSION)");
61 cryp
.len
= sizeof("what do ya want for nothing?")-1;
62 cryp
.src
= "what do ya want for nothing?";
64 cryp
.op
= COP_ENCRYPT
;
66 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
67 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
69 if (memcmp(mac
, sha1_out
, 20)!=0) {
71 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
72 printf("%.2x", (uint8_t)mac
[i
]);
75 fprintf(stderr
, "HASH test 1: failed\n");
77 if (debug
) fprintf(stderr
, "HASH test 1: passed\n");
80 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
81 perror("ioctl(CIOCFSESSION)");
86 memset(mac
, 0, sizeof(mac
));
89 sess
.mackey
= (uint8_t*)"Jefe";
91 sess
.mac
= CRYPTO_MD5_HMAC
;
92 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
93 perror("ioctl(CIOCGSESSION)");
98 cryp
.len
= sizeof("what do ya want for nothing?")-1;
99 cryp
.src
= "what do ya want for nothing?";
101 cryp
.op
= COP_ENCRYPT
;
103 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
104 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
106 if (memcmp(mac
, md5_hmac_out
, 16)!=0) {
108 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
109 printf("%.2x", (uint8_t)mac
[i
]);
112 fprintf(stderr
, "HMAC test 1: failed\n");
114 if (debug
) fprintf(stderr
, "HMAC test 1: passed\n");
117 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
118 perror("ioctl(CIOCFSESSION)");
122 /* Hash and encryption in one step test */
123 sess
.cipher
= CRYPTO_AES_CBC
;
124 sess
.mac
= CRYPTO_SHA1_HMAC
;
125 sess
.keylen
= KEY_SIZE
;
128 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
129 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
130 perror("ioctl(CIOCGSESSION)");
134 /* Encrypt data.in to data.encrypted */
136 cryp
.len
= sizeof(data
.in
);
138 cryp
.dst
= data
.encrypted
;
141 cryp
.op
= COP_ENCRYPT
;
143 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
144 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
146 memcpy(oldmac
, mac
, sizeof(mac
));
148 /* Decrypt data.encrypted to data.decrypted */
149 cryp
.src
= data
.encrypted
;
150 cryp
.dst
= data
.decrypted
;
151 cryp
.op
= COP_DECRYPT
;
153 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
154 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
156 /* Verify the result */
157 if (memcmp(data
.in
, data
.decrypted
, sizeof(data
.in
)) != 0) {
159 "FAIL: Decrypted data are different from the input data.\n");
162 printf("Crypt Test: passed\n");
164 if (memcmp(mac
, oldmac
, 20) != 0) {
166 "FAIL: Hash in decrypted data different than in encrypted.\n");
169 printf("HMAC Test 2: passed\n");
171 /* Finish crypto session */
172 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
173 perror("ioctl(CIOCFSESSION)");
183 struct session_op sess
;
184 struct crypt_op cryp
;
185 uint8_t mac
[AALG_MAX_RESULT_LEN
];
186 uint8_t oldmac
[AALG_MAX_RESULT_LEN
];
187 uint8_t md5_hmac_out
[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
188 uint8_t sha1_out
[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
191 memset(&sess
, 0, sizeof(sess
));
192 memset(&cryp
, 0, sizeof(cryp
));
194 /* Use the garbage that is on the stack :-) */
195 /* memset(&data, 0, sizeof(data)); */
197 /* SHA1 plain test */
198 memset(mac
, 0, sizeof(mac
));
201 sess
.mac
= CRYPTO_SHA1
;
202 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
203 perror("ioctl(CIOCGSESSION)");
208 cryp
.len
= sizeof("what do")-1;
209 cryp
.src
= "what do";
211 cryp
.op
= COP_ENCRYPT
;
212 cryp
.flags
= COP_FLAG_UPDATE
;
214 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
215 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
218 cryp
.len
= sizeof(" ya want for nothing?")-1;
219 cryp
.src
= " ya want for nothing?";
221 cryp
.op
= COP_ENCRYPT
;
222 cryp
.flags
= COP_FLAG_FINAL
;
224 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
225 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
227 if (memcmp(mac
, sha1_out
, 20)!=0) {
229 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
230 printf("%.2x", (uint8_t)mac
[i
]);
233 fprintf(stderr
, "HASH test [update]: failed\n");
235 if (debug
) fprintf(stderr
, "HASH test [update]: passed\n");
238 memset(mac
, 0, sizeof(mac
));
240 /* Finish crypto session */
241 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
242 perror("ioctl(CIOCFSESSION)");
253 int fd
= -1, cfd
= -1;
255 /* Open the crypto device */
256 fd
= open("/dev/crypto", O_RDWR
, 0);
258 perror("open(/dev/crypto)");
262 /* Clone file descriptor */
263 if (ioctl(fd
, CRIOGET
, &cfd
)) {
264 perror("ioctl(CRIOGET)");
268 /* Set close-on-exec (not really neede here) */
269 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
270 perror("fcntl(F_SETFD)");
274 /* Run the test itself */
275 if (test_crypto(cfd
))
278 if (test_extras(cfd
))
281 /* Close cloned descriptor */
283 perror("close(cfd)");
287 /* Close the original descriptor */