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"
19 #define DATA_SIZE 4096
22 #define SHA1_HASH_LEN 20
28 uint8_t in
[DATA_SIZE
],
34 struct session_op sess
;
36 uint8_t mac
[AALG_MAX_RESULT_LEN
];
37 uint8_t oldmac
[AALG_MAX_RESULT_LEN
];
38 uint8_t md5_hmac_out
[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
39 uint8_t sha1_out
[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
42 memset(&sess
, 0, sizeof(sess
));
43 memset(&cryp
, 0, sizeof(cryp
));
45 /* Use the garbage that is on the stack :-) */
46 /* memset(&data, 0, sizeof(data)); */
49 memset(mac
, 0, sizeof(mac
));
52 sess
.mac
= CRYPTO_SHA1
;
53 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
54 perror("ioctl(CIOCGSESSION)");
59 cryp
.len
= sizeof("what do ya want for nothing?")-1;
60 cryp
.src
= "what do ya want for nothing?";
62 cryp
.op
= COP_ENCRYPT
;
64 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
65 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
67 if (memcmp(mac
, sha1_out
, 20)!=0) {
69 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
70 printf("%.2x", (uint8_t)mac
[i
]);
73 fprintf(stderr
, "HASH test 1: failed\n");
75 fprintf(stderr
, "HASH test 1: passed\n");
78 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
79 perror("ioctl(CIOCFSESSION)");
84 memset(mac
, 0, sizeof(mac
));
87 sess
.mackey
= (uint8_t*)"Jefe";
89 sess
.mac
= CRYPTO_MD5_HMAC
;
90 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
91 perror("ioctl(CIOCGSESSION)");
96 cryp
.len
= sizeof("what do ya want for nothing?")-1;
97 cryp
.src
= "what do ya want for nothing?";
99 cryp
.op
= COP_ENCRYPT
;
101 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
102 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
104 if (memcmp(mac
, md5_hmac_out
, 16)!=0) {
106 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
107 printf("%.2x", (uint8_t)mac
[i
]);
110 fprintf(stderr
, "HMAC test 1: failed\n");
112 fprintf(stderr
, "HMAC test 1: passed\n");
115 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
116 perror("ioctl(CIOCFSESSION)");
120 /* Hash and encryption in one step test */
121 sess
.cipher
= CRYPTO_AES_CBC
;
122 sess
.mac
= CRYPTO_SHA1_HMAC
;
123 sess
.keylen
= KEY_SIZE
;
126 sess
.mackey
= (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
127 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
128 perror("ioctl(CIOCGSESSION)");
132 /* Encrypt data.in to data.encrypted */
134 cryp
.len
= sizeof(data
.in
);
136 cryp
.dst
= data
.encrypted
;
139 cryp
.op
= COP_ENCRYPT
;
141 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
142 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
144 memcpy(oldmac
, mac
, sizeof(mac
));
146 /* Decrypt data.encrypted to data.decrypted */
147 cryp
.src
= data
.encrypted
;
148 cryp
.dst
= data
.decrypted
;
149 cryp
.op
= COP_DECRYPT
;
151 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
152 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
154 /* Verify the result */
155 if (memcmp(data
.in
, data
.decrypted
, sizeof(data
.in
)) != 0) {
157 "FAIL: Decrypted data are different from the input data.\n");
160 printf("Crypt Test: passed\n");
162 if (memcmp(mac
, oldmac
, 20) != 0) {
164 "FAIL: Hash in decrypted data different than in encrypted.\n");
167 printf("HMAC Test 2: passed\n");
169 /* Finish crypto session */
170 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
171 perror("ioctl(CIOCFSESSION)");
181 struct session_op sess
;
182 struct crypt_op cryp
;
183 uint8_t mac
[AALG_MAX_RESULT_LEN
];
184 uint8_t oldmac
[AALG_MAX_RESULT_LEN
];
185 uint8_t md5_hmac_out
[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
186 uint8_t sha1_out
[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
189 memset(&sess
, 0, sizeof(sess
));
190 memset(&cryp
, 0, sizeof(cryp
));
192 /* Use the garbage that is on the stack :-) */
193 /* memset(&data, 0, sizeof(data)); */
195 /* SHA1 plain test */
196 memset(mac
, 0, sizeof(mac
));
199 sess
.mac
= CRYPTO_SHA1
;
200 if (ioctl(cfd
, CIOCGSESSION
, &sess
)) {
201 perror("ioctl(CIOCGSESSION)");
206 cryp
.len
= sizeof("what do")-1;
207 cryp
.src
= "what do";
209 cryp
.op
= COP_ENCRYPT
;
210 cryp
.flags
= COP_FLAG_UPDATE
;
212 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
213 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
216 cryp
.len
= sizeof(" ya want for nothing?")-1;
217 cryp
.src
= " ya want for nothing?";
219 cryp
.op
= COP_ENCRYPT
;
220 cryp
.flags
= COP_FLAG_FINAL
;
222 DO_OR_DIE(do_async_crypt(cfd
, &cryp
), 0);
223 DO_OR_DIE(do_async_fetch(cfd
, &cryp
), 0);
225 if (memcmp(mac
, sha1_out
, 20)!=0) {
227 for (i
=0;i
<SHA1_HASH_LEN
;i
++) {
228 printf("%.2x", (uint8_t)mac
[i
]);
231 fprintf(stderr
, "HASH test [update]: failed\n");
233 fprintf(stderr
, "HASH test [update]: passed\n");
236 memset(mac
, 0, sizeof(mac
));
238 /* Finish crypto session */
239 if (ioctl(cfd
, CIOCFSESSION
, &sess
.ses
)) {
240 perror("ioctl(CIOCFSESSION)");
251 int fd
= -1, cfd
= -1;
253 /* Open the crypto device */
254 fd
= open("/dev/crypto", O_RDWR
, 0);
256 perror("open(/dev/crypto)");
260 /* Clone file descriptor */
261 if (ioctl(fd
, CRIOGET
, &cfd
)) {
262 perror("ioctl(CRIOGET)");
266 /* Set close-on-exec (not really neede here) */
267 if (fcntl(cfd
, F_SETFD
, 1) == -1) {
268 perror("fcntl(F_SETFD)");
272 /* Run the test itself */
273 if (test_crypto(cfd
))
276 if (test_extras(cfd
))
279 /* Close cloned descriptor */
281 perror("close(cfd)");
285 /* Close the original descriptor */