]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/crypto/crypto_linux.c
8099193bf0682b97ca1c4f0156f4300fdcc68640
[thirdparty/hostap.git] / src / crypto / crypto_linux.c
1 /*
2 * Crypto wrapper for Linux kernel AF_ALG
3 * Copyright (c) 2017, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <linux/if_alg.h>
11
12 #include "common.h"
13 #include "crypto.h"
14 #include "md5.h"
15 #include "sha1.h"
16 #include "sha256.h"
17 #include "sha384.h"
18 #include "aes.h"
19
20
21 #ifndef SOL_ALG
22 #define SOL_ALG 279
23 #endif /* SOL_ALG */
24
25
26 static int linux_af_alg_socket(const char *type, const char *name)
27 {
28 struct sockaddr_alg sa;
29 int s;
30
31 if (TEST_FAIL())
32 return -1;
33
34 s = socket(AF_ALG, SOCK_SEQPACKET, 0);
35 if (s < 0) {
36 wpa_printf(MSG_ERROR, "%s: Failed to open AF_ALG socket: %s",
37 __func__, strerror(errno));
38 return -1;
39 }
40
41 os_memset(&sa, 0, sizeof(sa));
42 sa.salg_family = AF_ALG;
43 os_strlcpy((char *) sa.salg_type, type, sizeof(sa.salg_type));
44 os_strlcpy((char *) sa.salg_name, name, sizeof(sa.salg_type));
45 if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
46 wpa_printf(MSG_ERROR,
47 "%s: Failed to bind AF_ALG socket(%s,%s): %s",
48 __func__, type, name, strerror(errno));
49 close(s);
50 return -1;
51 }
52
53 return s;
54 }
55
56
57 static int linux_af_alg_hash_vector(const char *alg, const u8 *key,
58 size_t key_len, size_t num_elem,
59 const u8 *addr[], const size_t *len,
60 u8 *mac, size_t mac_len)
61 {
62 int s, t;
63 size_t i;
64 ssize_t res;
65 int ret = -1;
66
67 s = linux_af_alg_socket("hash", alg);
68 if (s < 0)
69 return -1;
70
71 if (key && setsockopt(s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
72 wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
73 __func__, strerror(errno));
74 close(s);
75 return -1;
76 }
77
78 t = accept(s, NULL, NULL);
79 if (t < 0) {
80 wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
81 __func__, strerror(errno));
82 close(s);
83 return -1;
84 }
85
86 for (i = 0; i < num_elem; i++) {
87 res = send(t, addr[i], len[i], i + 1 < num_elem ? MSG_MORE : 0);
88 if (res < 0) {
89 wpa_printf(MSG_ERROR,
90 "%s: send on AF_ALG socket failed: %s",
91 __func__, strerror(errno));
92 goto fail;
93 }
94 if ((size_t) res < len[i]) {
95 wpa_printf(MSG_ERROR,
96 "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
97 __func__, (int) res, (int) len[i]);
98 goto fail;
99 }
100 }
101
102 res = recv(t, mac, mac_len, 0);
103 if (res < 0) {
104 wpa_printf(MSG_ERROR,
105 "%s: recv on AF_ALG socket failed: %s",
106 __func__, strerror(errno));
107 goto fail;
108 }
109 if ((size_t) res < mac_len) {
110 wpa_printf(MSG_ERROR,
111 "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
112 __func__, (int) res, (int) mac_len);
113 goto fail;
114 }
115
116 ret = 0;
117 fail:
118 close(t);
119 close(s);
120
121 return ret;
122 }
123
124
125 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
126 {
127 return linux_af_alg_hash_vector("md4", NULL, 0, num_elem, addr, len,
128 mac, 16);
129 }
130
131
132 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
133 {
134 return linux_af_alg_hash_vector("md5", NULL, 0, num_elem, addr, len,
135 mac, MD5_MAC_LEN);
136 }
137
138
139 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
140 u8 *mac)
141 {
142 return linux_af_alg_hash_vector("sha1", NULL, 0, num_elem, addr, len,
143 mac, SHA1_MAC_LEN);
144 }
145
146
147 int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
148 u8 *mac)
149 {
150 return linux_af_alg_hash_vector("sha256", NULL, 0, num_elem, addr, len,
151 mac, SHA256_MAC_LEN);
152 }
153
154
155 int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
156 u8 *mac)
157 {
158 return linux_af_alg_hash_vector("sha384", NULL, 0, num_elem, addr, len,
159 mac, SHA384_MAC_LEN);
160 }
161
162
163 int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
164 u8 *mac)
165 {
166 return linux_af_alg_hash_vector("sha512", NULL, 0, num_elem, addr, len,
167 mac, 64);
168 }
169
170
171 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
172 const u8 *addr[], const size_t *len, u8 *mac)
173 {
174 return linux_af_alg_hash_vector("hmac(md5)", key, key_len, num_elem,
175 addr, len, mac, 16);
176 }
177
178
179 int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
180 u8 *mac)
181 {
182 return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
183 }
184
185
186 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
187 const u8 *addr[], const size_t *len, u8 *mac)
188 {
189 return linux_af_alg_hash_vector("hmac(sha1)", key, key_len, num_elem,
190 addr, len, mac, SHA1_MAC_LEN);
191 }
192
193
194 int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
195 u8 *mac)
196 {
197 return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
198 }
199
200
201 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
202 const u8 *addr[], const size_t *len, u8 *mac)
203 {
204 return linux_af_alg_hash_vector("hmac(sha256)", key, key_len, num_elem,
205 addr, len, mac, SHA256_MAC_LEN);
206 }
207
208
209 int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
210 size_t data_len, u8 *mac)
211 {
212 return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
213 }
214
215
216 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
217 const u8 *addr[], const size_t *len, u8 *mac)
218 {
219 return linux_af_alg_hash_vector("hmac(sha384)", key, key_len, num_elem,
220 addr, len, mac, SHA384_MAC_LEN);
221 }
222
223
224 int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
225 size_t data_len, u8 *mac)
226 {
227 return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
228 }
229
230
231 struct crypto_hash {
232 int s;
233 int t;
234 size_t mac_len;
235 int failed;
236 };
237
238
239 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
240 size_t key_len)
241 {
242 struct crypto_hash *ctx;
243 const char *name;
244
245 ctx = os_zalloc(sizeof(*ctx));
246 if (!ctx)
247 return NULL;
248
249 switch (alg) {
250 case CRYPTO_HASH_ALG_MD5:
251 name = "md5";
252 ctx->mac_len = MD5_MAC_LEN;
253 break;
254 case CRYPTO_HASH_ALG_SHA1:
255 name = "sha1";
256 ctx->mac_len = SHA1_MAC_LEN;
257 break;
258 case CRYPTO_HASH_ALG_HMAC_MD5:
259 name = "hmac(md5)";
260 ctx->mac_len = MD5_MAC_LEN;
261 break;
262 case CRYPTO_HASH_ALG_HMAC_SHA1:
263 name = "hmac(sha1)";
264 ctx->mac_len = SHA1_MAC_LEN;
265 break;
266 case CRYPTO_HASH_ALG_SHA256:
267 name = "sha256";
268 ctx->mac_len = SHA256_MAC_LEN;
269 break;
270 case CRYPTO_HASH_ALG_HMAC_SHA256:
271 name = "hmac(sha256)";
272 ctx->mac_len = SHA256_MAC_LEN;
273 break;
274 case CRYPTO_HASH_ALG_SHA384:
275 name = "sha384";
276 ctx->mac_len = SHA384_MAC_LEN;
277 break;
278 case CRYPTO_HASH_ALG_SHA512:
279 name = "sha512";
280 ctx->mac_len = 64;
281 break;
282 default:
283 os_free(ctx);
284 return NULL;
285 }
286
287 ctx->s = linux_af_alg_socket("hash", name);
288 if (ctx->s < 0) {
289 os_free(ctx);
290 return NULL;
291 }
292
293 if (key && key_len &&
294 setsockopt(ctx->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
295 wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
296 __func__, strerror(errno));
297 close(ctx->s);
298 os_free(ctx);
299 return NULL;
300 }
301
302 ctx->t = accept(ctx->s, NULL, NULL);
303 if (ctx->t < 0) {
304 wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
305 __func__, strerror(errno));
306 close(ctx->s);
307 os_free(ctx);
308 return NULL;
309 }
310
311 return ctx;
312 }
313
314
315 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
316 {
317 ssize_t res;
318
319 if (!ctx)
320 return;
321
322 res = send(ctx->t, data, len, MSG_MORE);
323 if (res < 0) {
324 wpa_printf(MSG_ERROR,
325 "%s: send on AF_ALG socket failed: %s",
326 __func__, strerror(errno));
327 ctx->failed = 1;
328 return;
329 }
330 if ((size_t) res < len) {
331 wpa_printf(MSG_ERROR,
332 "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
333 __func__, (int) res, (int) len);
334 ctx->failed = 1;
335 return;
336 }
337 }
338
339
340 static void crypto_hash_deinit(struct crypto_hash *ctx)
341 {
342 close(ctx->s);
343 close(ctx->t);
344 os_free(ctx);
345 }
346
347
348 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
349 {
350 ssize_t res;
351
352 if (!ctx)
353 return -2;
354
355 if (!mac || !len) {
356 crypto_hash_deinit(ctx);
357 return 0;
358 }
359
360 if (ctx->failed) {
361 crypto_hash_deinit(ctx);
362 return -2;
363 }
364
365 if (*len < ctx->mac_len) {
366 crypto_hash_deinit(ctx);
367 *len = ctx->mac_len;
368 return -1;
369 }
370 *len = ctx->mac_len;
371
372 res = recv(ctx->t, mac, ctx->mac_len, 0);
373 if (res < 0) {
374 wpa_printf(MSG_ERROR,
375 "%s: recv on AF_ALG socket failed: %s",
376 __func__, strerror(errno));
377 crypto_hash_deinit(ctx);
378 return -2;
379 }
380 if ((size_t) res < ctx->mac_len) {
381 wpa_printf(MSG_ERROR,
382 "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
383 __func__, (int) res, (int) ctx->mac_len);
384 crypto_hash_deinit(ctx);
385 return -2;
386 }
387
388 crypto_hash_deinit(ctx);
389 return 0;
390 }
391
392
393 struct linux_af_alg_skcipher {
394 int s;
395 int t;
396 };
397
398
399 static void linux_af_alg_skcipher_deinit(struct linux_af_alg_skcipher *skcipher)
400 {
401 if (!skcipher)
402 return;
403 if (skcipher->s >= 0)
404 close(skcipher->s);
405 if (skcipher->t >= 0)
406 close(skcipher->t);
407 os_free(skcipher);
408 }
409
410
411 static struct linux_af_alg_skcipher *
412 linux_af_alg_skcipher(const char *alg, const u8 *key, size_t key_len)
413 {
414 struct linux_af_alg_skcipher *skcipher;
415
416 skcipher = os_zalloc(sizeof(*skcipher));
417 if (!skcipher)
418 goto fail;
419 skcipher->t = -1;
420
421 skcipher->s = linux_af_alg_socket("skcipher", alg);
422 if (skcipher->s < 0)
423 goto fail;
424
425 if (setsockopt(skcipher->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
426 wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
427 __func__, strerror(errno));
428 goto fail;
429 }
430
431 skcipher->t = accept(skcipher->s, NULL, NULL);
432 if (skcipher->t < 0) {
433 wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
434 __func__, strerror(errno));
435 goto fail;
436 }
437
438 return skcipher;
439 fail:
440 linux_af_alg_skcipher_deinit(skcipher);
441 return NULL;
442 }
443
444
445 static int linux_af_alg_skcipher_oper(struct linux_af_alg_skcipher *skcipher,
446 int enc, const u8 *in, u8 *out)
447 {
448 char buf[CMSG_SPACE(sizeof(u32))];
449 struct iovec io[1];
450 struct msghdr msg;
451 struct cmsghdr *hdr;
452 ssize_t ret;
453 u32 *op;
454
455 io[0].iov_base = (void *) in;
456 io[0].iov_len = AES_BLOCK_SIZE;
457 os_memset(&msg, 0, sizeof(msg));
458 os_memset(buf, 0, sizeof(buf));
459 msg.msg_control = buf;
460 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
461 msg.msg_iov = io;
462 msg.msg_iovlen = 1;
463 hdr = CMSG_FIRSTHDR(&msg);
464 hdr->cmsg_level = SOL_ALG;
465 hdr->cmsg_type = ALG_SET_OP;
466 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
467 op = (u32 *) CMSG_DATA(hdr);
468 *op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
469
470 ret = sendmsg(skcipher->t, &msg, 0);
471 if (ret < 0) {
472 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
473 __func__, strerror(errno));
474 return -1;
475 }
476
477 ret = read(skcipher->t, out, AES_BLOCK_SIZE);
478 if (ret < 0) {
479 wpa_printf(MSG_ERROR, "%s: read failed: %s",
480 __func__, strerror(errno));
481 return -1;
482 }
483 if (ret < AES_BLOCK_SIZE) {
484 wpa_printf(MSG_ERROR,
485 "%s: read did not return full data (%d/%d)",
486 __func__, (int) ret, AES_BLOCK_SIZE);
487 return -1;
488 }
489
490 return 0;
491 }
492
493
494 void * aes_encrypt_init(const u8 *key, size_t len)
495 {
496 return linux_af_alg_skcipher("ecb(aes)", key, len);
497 }
498
499
500 int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
501 {
502 struct linux_af_alg_skcipher *skcipher = ctx;
503
504 return linux_af_alg_skcipher_oper(skcipher, 1, plain, crypt);
505 }
506
507
508 void aes_encrypt_deinit(void *ctx)
509 {
510 linux_af_alg_skcipher_deinit(ctx);
511 }
512
513
514 void * aes_decrypt_init(const u8 *key, size_t len)
515 {
516 return linux_af_alg_skcipher("ecb(aes)", key, len);
517 }
518
519
520 int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
521 {
522 struct linux_af_alg_skcipher *skcipher = ctx;
523
524 return linux_af_alg_skcipher_oper(skcipher, 0, crypt, plain);
525 }
526
527
528 void aes_decrypt_deinit(void *ctx)
529 {
530 linux_af_alg_skcipher_deinit(ctx);
531 }
532
533
534 int rc4_skip(const u8 *key, size_t keylen, size_t skip,
535 u8 *data, size_t data_len)
536 {
537 struct linux_af_alg_skcipher *skcipher;
538 u8 *skip_buf;
539 char buf[CMSG_SPACE(sizeof(u32))];
540 struct iovec io[2];
541 struct msghdr msg;
542 struct cmsghdr *hdr;
543 ssize_t ret;
544 u32 *op;
545
546 skip_buf = os_zalloc(skip + 1);
547 if (!skip_buf)
548 return -1;
549 skcipher = linux_af_alg_skcipher("ecb(arc4)", key, keylen);
550 if (!skcipher) {
551 os_free(skip_buf);
552 return -1;
553 }
554
555 io[0].iov_base = skip_buf;
556 io[0].iov_len = skip;
557 io[1].iov_base = data;
558 io[1].iov_len = data_len;
559 os_memset(&msg, 0, sizeof(msg));
560 os_memset(buf, 0, sizeof(buf));
561 msg.msg_control = buf;
562 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
563 msg.msg_iov = io;
564 msg.msg_iovlen = 2;
565 hdr = CMSG_FIRSTHDR(&msg);
566 hdr->cmsg_level = SOL_ALG;
567 hdr->cmsg_type = ALG_SET_OP;
568 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
569 op = (u32 *) CMSG_DATA(hdr);
570 *op = ALG_OP_ENCRYPT;
571
572 ret = sendmsg(skcipher->t, &msg, 0);
573 if (ret < 0) {
574 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
575 __func__, strerror(errno));
576 os_free(skip_buf);
577 linux_af_alg_skcipher_deinit(skcipher);
578 return -1;
579 }
580 os_free(skip_buf);
581
582 msg.msg_control = NULL;
583 msg.msg_controllen = 0;
584 ret = recvmsg(skcipher->t, &msg, 0);
585 if (ret < 0) {
586 wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
587 __func__, strerror(errno));
588 linux_af_alg_skcipher_deinit(skcipher);
589 return -1;
590 }
591 linux_af_alg_skcipher_deinit(skcipher);
592
593 if ((size_t) ret < skip + data_len) {
594 wpa_printf(MSG_ERROR,
595 "%s: recvmsg did not return full data (%d/%d)",
596 __func__, (int) ret, (int) (skip + data_len));
597 return -1;
598 }
599
600 return 0;
601 }
602
603
604 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
605 {
606 u8 pkey[8], next, tmp;
607 int i;
608 struct linux_af_alg_skcipher *skcipher;
609 char buf[CMSG_SPACE(sizeof(u32))];
610 struct iovec io[1];
611 struct msghdr msg;
612 struct cmsghdr *hdr;
613 ssize_t ret;
614 u32 *op;
615 int res = -1;
616
617 /* Add parity bits to the key */
618 next = 0;
619 for (i = 0; i < 7; i++) {
620 tmp = key[i];
621 pkey[i] = (tmp >> i) | next | 1;
622 next = tmp << (7 - i);
623 }
624 pkey[i] = next | 1;
625
626 skcipher = linux_af_alg_skcipher("ecb(des)", pkey, sizeof(pkey));
627 if (!skcipher)
628 goto fail;
629
630 io[0].iov_base = (void *) clear;
631 io[0].iov_len = 8;
632 os_memset(&msg, 0, sizeof(msg));
633 os_memset(buf, 0, sizeof(buf));
634 msg.msg_control = buf;
635 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
636 msg.msg_iov = io;
637 msg.msg_iovlen = 1;
638 hdr = CMSG_FIRSTHDR(&msg);
639 hdr->cmsg_level = SOL_ALG;
640 hdr->cmsg_type = ALG_SET_OP;
641 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
642 op = (u32 *) CMSG_DATA(hdr);
643 *op = ALG_OP_ENCRYPT;
644
645 ret = sendmsg(skcipher->t, &msg, 0);
646 if (ret < 0) {
647 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
648 __func__, strerror(errno));
649 goto fail;
650 }
651
652 ret = read(skcipher->t, cypher, 8);
653 if (ret < 0) {
654 wpa_printf(MSG_ERROR, "%s: read failed: %s",
655 __func__, strerror(errno));
656 goto fail;
657 }
658 if (ret < 8) {
659 wpa_printf(MSG_ERROR,
660 "%s: read did not return full data (%d/8)",
661 __func__, (int) ret);
662 goto fail;
663 }
664
665 res = 0;
666 fail:
667 linux_af_alg_skcipher_deinit(skcipher);
668 return res;
669 }
670
671
672 static int aes_128_cbc_oper(const u8 *key, int enc, const u8 *iv,
673 u8 *data, size_t data_len)
674 {
675 struct linux_af_alg_skcipher *skcipher;
676 char buf[100];
677 struct iovec io[1];
678 struct msghdr msg;
679 struct cmsghdr *hdr;
680 ssize_t ret;
681 u32 *op;
682 struct af_alg_iv *alg_iv;
683 size_t iv_len = AES_BLOCK_SIZE;
684
685 skcipher = linux_af_alg_skcipher("cbc(aes)", key, 16);
686 if (!skcipher)
687 return -1;
688
689 io[0].iov_base = (void *) data;
690 io[0].iov_len = data_len;
691 os_memset(&msg, 0, sizeof(msg));
692 os_memset(buf, 0, sizeof(buf));
693 msg.msg_control = buf;
694 msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
695 CMSG_SPACE(sizeof(*alg_iv) + iv_len);
696 msg.msg_iov = io;
697 msg.msg_iovlen = 1;
698
699 hdr = CMSG_FIRSTHDR(&msg);
700 hdr->cmsg_level = SOL_ALG;
701 hdr->cmsg_type = ALG_SET_OP;
702 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
703 op = (u32 *) CMSG_DATA(hdr);
704 *op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
705
706 hdr = CMSG_NXTHDR(&msg, hdr);
707 hdr->cmsg_level = SOL_ALG;
708 hdr->cmsg_type = ALG_SET_IV;
709 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
710 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
711 alg_iv->ivlen = iv_len;
712 os_memcpy(alg_iv->iv, iv, iv_len);
713
714 ret = sendmsg(skcipher->t, &msg, 0);
715 if (ret < 0) {
716 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
717 __func__, strerror(errno));
718 linux_af_alg_skcipher_deinit(skcipher);
719 return -1;
720 }
721
722 ret = recvmsg(skcipher->t, &msg, 0);
723 if (ret < 0) {
724 wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
725 __func__, strerror(errno));
726 linux_af_alg_skcipher_deinit(skcipher);
727 return -1;
728 }
729 if ((size_t) ret < data_len) {
730 wpa_printf(MSG_ERROR,
731 "%s: recvmsg not return full data (%d/%d)",
732 __func__, (int) ret, (int) data_len);
733 linux_af_alg_skcipher_deinit(skcipher);
734 return -1;
735 }
736
737 linux_af_alg_skcipher_deinit(skcipher);
738 return 0;
739 }
740
741
742 int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
743 {
744 return aes_128_cbc_oper(key, 1, iv, data, data_len);
745 }
746
747
748 int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
749 {
750 return aes_128_cbc_oper(key, 0, iv, data, data_len);
751 }
752
753
754 int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
755 const u8 *addr[], const size_t *len, u8 *mac)
756 {
757 return linux_af_alg_hash_vector("cmac(aes)", key, key_len, num_elem,
758 addr, len, mac, AES_BLOCK_SIZE);
759 }
760
761
762 int omac1_aes_128_vector(const u8 *key, size_t num_elem,
763 const u8 *addr[], const size_t *len, u8 *mac)
764 {
765 return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
766 }
767
768
769 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
770 {
771 return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
772 }
773
774
775 int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
776 {
777 return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
778 }
779
780
781 int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
782 u8 *plain)
783 {
784 struct linux_af_alg_skcipher *skcipher;
785 char buf[100];
786 struct iovec io[1];
787 struct msghdr msg;
788 struct cmsghdr *hdr;
789 ssize_t ret;
790 u32 *op;
791 struct af_alg_iv *alg_iv;
792 size_t iv_len = 8;
793
794 skcipher = linux_af_alg_skcipher("kw(aes)", kek, kek_len);
795 if (!skcipher)
796 return -1;
797
798 io[0].iov_base = (void *) (cipher + iv_len);
799 io[0].iov_len = n * 8;
800 os_memset(&msg, 0, sizeof(msg));
801 os_memset(buf, 0, sizeof(buf));
802 msg.msg_control = buf;
803 msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
804 CMSG_SPACE(sizeof(*alg_iv) + iv_len);
805 msg.msg_iov = io;
806 msg.msg_iovlen = 1;
807
808 hdr = CMSG_FIRSTHDR(&msg);
809 hdr->cmsg_level = SOL_ALG;
810 hdr->cmsg_type = ALG_SET_OP;
811 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
812 op = (u32 *) CMSG_DATA(hdr);
813 *op = ALG_OP_DECRYPT;
814
815 hdr = CMSG_NXTHDR(&msg, hdr);
816 hdr->cmsg_level = SOL_ALG;
817 hdr->cmsg_type = ALG_SET_IV;
818 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
819 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
820 alg_iv->ivlen = iv_len;
821 os_memcpy(alg_iv->iv, cipher, iv_len);
822
823 ret = sendmsg(skcipher->t, &msg, 0);
824 if (ret < 0) {
825 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
826 __func__, strerror(errno));
827 return -1;
828 }
829
830 ret = read(skcipher->t, plain, n * 8);
831 if (ret < 0) {
832 wpa_printf(MSG_ERROR, "%s: read failed: %s",
833 __func__, strerror(errno));
834 linux_af_alg_skcipher_deinit(skcipher);
835 return -1;
836 }
837 if (ret < n * 8) {
838 wpa_printf(MSG_ERROR,
839 "%s: read not return full data (%d/%d)",
840 __func__, (int) ret, n * 8);
841 linux_af_alg_skcipher_deinit(skcipher);
842 return -1;
843 }
844
845 linux_af_alg_skcipher_deinit(skcipher);
846 return 0;
847 }
848
849
850 struct crypto_cipher {
851 struct linux_af_alg_skcipher *skcipher;
852 };
853
854
855 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
856 const u8 *iv, const u8 *key,
857 size_t key_len)
858 {
859 struct crypto_cipher *ctx;
860 const char *name;
861 struct af_alg_iv *alg_iv;
862 size_t iv_len = 0;
863 char buf[100];
864 struct msghdr msg;
865 struct cmsghdr *hdr;
866 ssize_t ret;
867
868 ctx = os_zalloc(sizeof(*ctx));
869 if (!ctx)
870 return NULL;
871
872 switch (alg) {
873 case CRYPTO_CIPHER_ALG_RC4:
874 name = "ecb(arc4)";
875 break;
876 case CRYPTO_CIPHER_ALG_AES:
877 name = "cbc(aes)";
878 iv_len = AES_BLOCK_SIZE;
879 break;
880 case CRYPTO_CIPHER_ALG_3DES:
881 name = "cbc(des3_ede)";
882 iv_len = 8;
883 break;
884 case CRYPTO_CIPHER_ALG_DES:
885 name = "cbc(des)";
886 iv_len = 8;
887 break;
888 default:
889 os_free(ctx);
890 return NULL;
891 }
892
893 ctx->skcipher = linux_af_alg_skcipher(name, key, key_len);
894 if (!ctx->skcipher) {
895 os_free(ctx);
896 return NULL;
897 }
898
899 if (iv && iv_len) {
900 os_memset(&msg, 0, sizeof(msg));
901 os_memset(buf, 0, sizeof(buf));
902 msg.msg_control = buf;
903 msg.msg_controllen = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
904 hdr = CMSG_FIRSTHDR(&msg);
905 hdr->cmsg_level = SOL_ALG;
906 hdr->cmsg_type = ALG_SET_IV;
907 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
908 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
909 alg_iv->ivlen = iv_len;
910 os_memcpy(alg_iv->iv, iv, iv_len);
911
912 ret = sendmsg(ctx->skcipher->t, &msg, 0);
913 if (ret < 0) {
914 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
915 __func__, strerror(errno));
916 linux_af_alg_skcipher_deinit(ctx->skcipher);
917 os_free(ctx);
918 return NULL;
919 }
920 }
921
922 return ctx;
923 }
924
925
926 static int crypto_cipher_oper(struct crypto_cipher *ctx, u32 type, const u8 *in,
927 u8 *out, size_t len)
928 {
929 char buf[CMSG_SPACE(sizeof(u32))];
930 struct iovec io[1];
931 struct msghdr msg;
932 struct cmsghdr *hdr;
933 ssize_t ret;
934 u32 *op;
935
936 io[0].iov_base = (void *) in;
937 io[0].iov_len = len;
938 os_memset(&msg, 0, sizeof(msg));
939 os_memset(buf, 0, sizeof(buf));
940 msg.msg_control = buf;
941 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
942 msg.msg_iov = io;
943 msg.msg_iovlen = 1;
944 hdr = CMSG_FIRSTHDR(&msg);
945 hdr->cmsg_level = SOL_ALG;
946 hdr->cmsg_type = ALG_SET_OP;
947 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
948 op = (u32 *) CMSG_DATA(hdr);
949 *op = type;
950
951 ret = sendmsg(ctx->skcipher->t, &msg, 0);
952 if (ret < 0) {
953 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
954 __func__, strerror(errno));
955 return -1;
956 }
957
958 ret = read(ctx->skcipher->t, out, len);
959 if (ret < 0) {
960 wpa_printf(MSG_ERROR, "%s: read failed: %s",
961 __func__, strerror(errno));
962 return -1;
963 }
964 if (ret < (ssize_t) len) {
965 wpa_printf(MSG_ERROR,
966 "%s: read did not return full data (%d/%d)",
967 __func__, (int) ret, (int) len);
968 return -1;
969 }
970
971 return 0;
972 }
973
974
975 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
976 u8 *crypt, size_t len)
977 {
978 return crypto_cipher_oper(ctx, ALG_OP_ENCRYPT, plain, crypt, len);
979 }
980
981
982 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
983 u8 *plain, size_t len)
984 {
985 return crypto_cipher_oper(ctx, ALG_OP_DECRYPT, crypt, plain, len);
986 }
987
988
989 void crypto_cipher_deinit(struct crypto_cipher *ctx)
990 {
991 if (ctx) {
992 linux_af_alg_skcipher_deinit(ctx->skcipher);
993 os_free(ctx);
994 }
995 }
996
997
998 int crypto_global_init(void)
999 {
1000 return 0;
1001 }
1002
1003
1004 void crypto_global_deinit(void)
1005 {
1006 }