export the alignmask but stay compatible to OCF
[cryptodev-linux.git] / examples / async_hmac.c
blobbe0275219246b39d454c5e710aa2855e290329ad
1 /*
2 * Demo on how to use /dev/crypto device for HMAC.
4 * Placed under public domain.
6 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11 #include <poll.h>
12 #include <stdint.h>
14 #include <sys/ioctl.h>
15 #include <crypto/cryptodev.h>
17 #include "testhelper.h"
19 #define DATA_SIZE 4096
20 #define BLOCK_SIZE 16
21 #define KEY_SIZE 16
22 #define SHA1_HASH_LEN 20
24 static int
25 test_crypto(int cfd)
27 struct {
28 uint8_t in[DATA_SIZE],
29 encrypted[DATA_SIZE],
30 decrypted[DATA_SIZE],
31 iv[BLOCK_SIZE],
32 key[KEY_SIZE];
33 } data;
34 struct session_op sess;
35 struct crypt_op cryp;
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";
40 int i;
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)); */
48 /* SHA1 plain test */
49 memset(mac, 0, sizeof(mac));
51 sess.cipher = 0;
52 sess.mac = CRYPTO_SHA1;
53 if (ioctl(cfd, CIOCGSESSION, &sess)) {
54 perror("ioctl(CIOCGSESSION)");
55 return 1;
58 cryp.ses = sess.ses;
59 cryp.len = sizeof("what do ya want for nothing?")-1;
60 cryp.src = "what do ya want for nothing?";
61 cryp.mac = mac;
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) {
68 printf("mac: ");
69 for (i=0;i<SHA1_HASH_LEN;i++) {
70 printf("%.2x", (uint8_t)mac[i]);
72 puts("\n");
73 fprintf(stderr, "HASH test 1: failed\n");
74 } else {
75 fprintf(stderr, "HASH test 1: passed\n");
78 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
79 perror("ioctl(CIOCFSESSION)");
80 return 1;
83 /* MD5-HMAC test */
84 memset(mac, 0, sizeof(mac));
86 sess.cipher = 0;
87 sess.mackey = (uint8_t*)"Jefe";
88 sess.mackeylen = 4;
89 sess.mac = CRYPTO_MD5_HMAC;
90 if (ioctl(cfd, CIOCGSESSION, &sess)) {
91 perror("ioctl(CIOCGSESSION)");
92 return 1;
95 cryp.ses = sess.ses;
96 cryp.len = sizeof("what do ya want for nothing?")-1;
97 cryp.src = "what do ya want for nothing?";
98 cryp.mac = mac;
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) {
105 printf("mac: ");
106 for (i=0;i<SHA1_HASH_LEN;i++) {
107 printf("%.2x", (uint8_t)mac[i]);
109 puts("\n");
110 fprintf(stderr, "HMAC test 1: failed\n");
111 } else {
112 fprintf(stderr, "HMAC test 1: passed\n");
115 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
116 perror("ioctl(CIOCFSESSION)");
117 return 1;
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;
124 sess.key = data.key;
125 sess.mackeylen = 16;
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)");
129 return 1;
132 /* Encrypt data.in to data.encrypted */
133 cryp.ses = sess.ses;
134 cryp.len = sizeof(data.in);
135 cryp.src = data.in;
136 cryp.dst = data.encrypted;
137 cryp.iv = data.iv;
138 cryp.mac = mac;
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) {
156 fprintf(stderr,
157 "FAIL: Decrypted data are different from the input data.\n");
158 return 1;
159 } else
160 printf("Crypt Test: passed\n");
162 if (memcmp(mac, oldmac, 20) != 0) {
163 fprintf(stderr,
164 "FAIL: Hash in decrypted data different than in encrypted.\n");
165 return 1;
166 } else
167 printf("HMAC Test 2: passed\n");
169 /* Finish crypto session */
170 if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
171 perror("ioctl(CIOCFSESSION)");
172 return 1;
175 return 0;
178 static int
179 test_extras(int cfd)
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";
187 int i;
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));
198 sess.cipher = 0;
199 sess.mac = CRYPTO_SHA1;
200 if (ioctl(cfd, CIOCGSESSION, &sess)) {
201 perror("ioctl(CIOCGSESSION)");
202 return 1;
205 cryp.ses = sess.ses;
206 cryp.len = sizeof("what do")-1;
207 cryp.src = "what do";
208 cryp.mac = mac;
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);
215 cryp.ses = sess.ses;
216 cryp.len = sizeof(" ya want for nothing?")-1;
217 cryp.src = " ya want for nothing?";
218 cryp.mac = mac;
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) {
226 printf("mac: ");
227 for (i=0;i<SHA1_HASH_LEN;i++) {
228 printf("%.2x", (uint8_t)mac[i]);
230 puts("\n");
231 fprintf(stderr, "HASH test [update]: failed\n");
232 } else {
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)");
241 return 1;
244 return 0;
249 main()
251 int fd = -1, cfd = -1;
253 /* Open the crypto device */
254 fd = open("/dev/crypto", O_RDWR, 0);
255 if (fd < 0) {
256 perror("open(/dev/crypto)");
257 return 1;
260 /* Clone file descriptor */
261 if (ioctl(fd, CRIOGET, &cfd)) {
262 perror("ioctl(CRIOGET)");
263 return 1;
266 /* Set close-on-exec (not really neede here) */
267 if (fcntl(cfd, F_SETFD, 1) == -1) {
268 perror("fcntl(F_SETFD)");
269 return 1;
272 /* Run the test itself */
273 if (test_crypto(cfd))
274 return 1;
276 if (test_extras(cfd))
277 return 1;
279 /* Close cloned descriptor */
280 if (close(cfd)) {
281 perror("close(cfd)");
282 return 1;
285 /* Close the original descriptor */
286 if (close(fd)) {
287 perror("close(fd)");
288 return 1;
291 return 0;