xref: /freebsd/contrib/wpa/src/crypto/crypto_linux.c (revision 52c2bb75163559a6e2866ad374a7de67a4ea1273)
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 
390 	if (TEST_FAIL())
391 		return -1;
392 	return 0;
393 }
394 
395 
396 struct linux_af_alg_skcipher {
397 	int s;
398 	int t;
399 };
400 
401 
402 static void linux_af_alg_skcipher_deinit(struct linux_af_alg_skcipher *skcipher)
403 {
404 	if (!skcipher)
405 		return;
406 	if (skcipher->s >= 0)
407 		close(skcipher->s);
408 	if (skcipher->t >= 0)
409 		close(skcipher->t);
410 	os_free(skcipher);
411 }
412 
413 
414 static struct linux_af_alg_skcipher *
415 linux_af_alg_skcipher(const char *alg, const u8 *key, size_t key_len)
416 {
417 	struct linux_af_alg_skcipher *skcipher;
418 
419 	skcipher = os_zalloc(sizeof(*skcipher));
420 	if (!skcipher)
421 		goto fail;
422 	skcipher->t = -1;
423 
424 	skcipher->s = linux_af_alg_socket("skcipher", alg);
425 	if (skcipher->s < 0)
426 		goto fail;
427 
428 	if (setsockopt(skcipher->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
429 		wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
430 			   __func__, strerror(errno));
431 		goto fail;
432 	}
433 
434 	skcipher->t = accept(skcipher->s, NULL, NULL);
435 	if (skcipher->t < 0) {
436 		wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
437 			   __func__, strerror(errno));
438 		goto fail;
439 	}
440 
441 	return skcipher;
442 fail:
443 	linux_af_alg_skcipher_deinit(skcipher);
444 	return NULL;
445 }
446 
447 
448 static int linux_af_alg_skcipher_oper(struct linux_af_alg_skcipher *skcipher,
449 				      int enc, const u8 *in, u8 *out)
450 {
451 	char buf[CMSG_SPACE(sizeof(u32))];
452 	struct iovec io[1];
453 	struct msghdr msg;
454 	struct cmsghdr *hdr;
455 	ssize_t ret;
456 	u32 *op;
457 
458 	io[0].iov_base = (void *) in;
459 	io[0].iov_len = AES_BLOCK_SIZE;
460 	os_memset(&msg, 0, sizeof(msg));
461 	os_memset(buf, 0, sizeof(buf));
462 	msg.msg_control = buf;
463 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
464 	msg.msg_iov = io;
465 	msg.msg_iovlen = 1;
466 	hdr = CMSG_FIRSTHDR(&msg);
467 	hdr->cmsg_level = SOL_ALG;
468 	hdr->cmsg_type = ALG_SET_OP;
469 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
470 	op = (u32 *) CMSG_DATA(hdr);
471 	*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
472 
473 	ret = sendmsg(skcipher->t, &msg, 0);
474 	if (ret < 0) {
475 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
476 			   __func__, strerror(errno));
477 		return -1;
478 	}
479 
480 	ret = read(skcipher->t, out, AES_BLOCK_SIZE);
481 	if (ret < 0) {
482 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
483 			   __func__, strerror(errno));
484 		return -1;
485 	}
486 	if (ret < AES_BLOCK_SIZE) {
487 		wpa_printf(MSG_ERROR,
488 			   "%s: read did not return full data (%d/%d)",
489 			   __func__, (int) ret, AES_BLOCK_SIZE);
490 		return -1;
491 	}
492 
493 	return 0;
494 }
495 
496 
497 void * aes_encrypt_init(const u8 *key, size_t len)
498 {
499 	return linux_af_alg_skcipher("ecb(aes)", key, len);
500 }
501 
502 
503 int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
504 {
505 	struct linux_af_alg_skcipher *skcipher = ctx;
506 
507 	return linux_af_alg_skcipher_oper(skcipher, 1, plain, crypt);
508 }
509 
510 
511 void aes_encrypt_deinit(void *ctx)
512 {
513 	linux_af_alg_skcipher_deinit(ctx);
514 }
515 
516 
517 void * aes_decrypt_init(const u8 *key, size_t len)
518 {
519 	return linux_af_alg_skcipher("ecb(aes)", key, len);
520 }
521 
522 
523 int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
524 {
525 	struct linux_af_alg_skcipher *skcipher = ctx;
526 
527 	return linux_af_alg_skcipher_oper(skcipher, 0, crypt, plain);
528 }
529 
530 
531 void aes_decrypt_deinit(void *ctx)
532 {
533 	linux_af_alg_skcipher_deinit(ctx);
534 }
535 
536 
537 int rc4_skip(const u8 *key, size_t keylen, size_t skip,
538 	     u8 *data, size_t data_len)
539 {
540 	struct linux_af_alg_skcipher *skcipher;
541 	u8 *skip_buf;
542 	char buf[CMSG_SPACE(sizeof(u32))];
543 	struct iovec io[2];
544 	struct msghdr msg;
545 	struct cmsghdr *hdr;
546 	ssize_t ret;
547 	u32 *op;
548 
549 	skip_buf = os_zalloc(skip + 1);
550 	if (!skip_buf)
551 		return -1;
552 	skcipher = linux_af_alg_skcipher("ecb(arc4)", key, keylen);
553 	if (!skcipher) {
554 		os_free(skip_buf);
555 		return -1;
556 	}
557 
558 	io[0].iov_base = skip_buf;
559 	io[0].iov_len = skip;
560 	io[1].iov_base = data;
561 	io[1].iov_len = data_len;
562 	os_memset(&msg, 0, sizeof(msg));
563 	os_memset(buf, 0, sizeof(buf));
564 	msg.msg_control = buf;
565 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
566 	msg.msg_iov = io;
567 	msg.msg_iovlen = 2;
568 	hdr = CMSG_FIRSTHDR(&msg);
569 	hdr->cmsg_level = SOL_ALG;
570 	hdr->cmsg_type = ALG_SET_OP;
571 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
572 	op = (u32 *) CMSG_DATA(hdr);
573 	*op = ALG_OP_ENCRYPT;
574 
575 	ret = sendmsg(skcipher->t, &msg, 0);
576 	if (ret < 0) {
577 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
578 			   __func__, strerror(errno));
579 		os_free(skip_buf);
580 		linux_af_alg_skcipher_deinit(skcipher);
581 		return -1;
582 	}
583 	os_free(skip_buf);
584 
585 	msg.msg_control = NULL;
586 	msg.msg_controllen = 0;
587 	ret = recvmsg(skcipher->t, &msg, 0);
588 	if (ret < 0) {
589 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
590 			   __func__, strerror(errno));
591 		linux_af_alg_skcipher_deinit(skcipher);
592 		return -1;
593 	}
594 	linux_af_alg_skcipher_deinit(skcipher);
595 
596 	if ((size_t) ret < skip + data_len) {
597 		wpa_printf(MSG_ERROR,
598 			   "%s: recvmsg did not return full data (%d/%d)",
599 			   __func__, (int) ret, (int) (skip + data_len));
600 		return -1;
601 	}
602 
603 	return 0;
604 }
605 
606 
607 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
608 {
609 	u8 pkey[8], next, tmp;
610 	int i;
611 	struct linux_af_alg_skcipher *skcipher;
612 	char buf[CMSG_SPACE(sizeof(u32))];
613 	struct iovec io[1];
614 	struct msghdr msg;
615 	struct cmsghdr *hdr;
616 	ssize_t ret;
617 	u32 *op;
618 	int res = -1;
619 
620 	/* Add parity bits to the key */
621 	next = 0;
622 	for (i = 0; i < 7; i++) {
623 		tmp = key[i];
624 		pkey[i] = (tmp >> i) | next | 1;
625 		next = tmp << (7 - i);
626 	}
627 	pkey[i] = next | 1;
628 
629 	skcipher = linux_af_alg_skcipher("ecb(des)", pkey, sizeof(pkey));
630 	if (!skcipher)
631 		goto fail;
632 
633 	io[0].iov_base = (void *) clear;
634 	io[0].iov_len = 8;
635 	os_memset(&msg, 0, sizeof(msg));
636 	os_memset(buf, 0, sizeof(buf));
637 	msg.msg_control = buf;
638 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
639 	msg.msg_iov = io;
640 	msg.msg_iovlen = 1;
641 	hdr = CMSG_FIRSTHDR(&msg);
642 	hdr->cmsg_level = SOL_ALG;
643 	hdr->cmsg_type = ALG_SET_OP;
644 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
645 	op = (u32 *) CMSG_DATA(hdr);
646 	*op = ALG_OP_ENCRYPT;
647 
648 	ret = sendmsg(skcipher->t, &msg, 0);
649 	if (ret < 0) {
650 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
651 			   __func__, strerror(errno));
652 		goto fail;
653 	}
654 
655 	ret = read(skcipher->t, cypher, 8);
656 	if (ret < 0) {
657 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
658 			   __func__, strerror(errno));
659 		goto fail;
660 	}
661 	if (ret < 8) {
662 		wpa_printf(MSG_ERROR,
663 			   "%s: read did not return full data (%d/8)",
664 			   __func__, (int) ret);
665 		goto fail;
666 	}
667 
668 	res = 0;
669 fail:
670 	linux_af_alg_skcipher_deinit(skcipher);
671 	return res;
672 }
673 
674 
675 static int aes_128_cbc_oper(const u8 *key, int enc, const u8 *iv,
676 			    u8 *data, size_t data_len)
677 {
678 	struct linux_af_alg_skcipher *skcipher;
679 	char buf[100];
680 	struct iovec io[1];
681 	struct msghdr msg;
682 	struct cmsghdr *hdr;
683 	ssize_t ret;
684 	u32 *op;
685 	struct af_alg_iv *alg_iv;
686 	size_t iv_len = AES_BLOCK_SIZE;
687 
688 	skcipher = linux_af_alg_skcipher("cbc(aes)", key, 16);
689 	if (!skcipher)
690 		return -1;
691 
692 	io[0].iov_base = (void *) data;
693 	io[0].iov_len = data_len;
694 	os_memset(&msg, 0, sizeof(msg));
695 	os_memset(buf, 0, sizeof(buf));
696 	msg.msg_control = buf;
697 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
698 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
699 	msg.msg_iov = io;
700 	msg.msg_iovlen = 1;
701 
702 	hdr = CMSG_FIRSTHDR(&msg);
703 	hdr->cmsg_level = SOL_ALG;
704 	hdr->cmsg_type = ALG_SET_OP;
705 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
706 	op = (u32 *) CMSG_DATA(hdr);
707 	*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
708 
709 	hdr = CMSG_NXTHDR(&msg, hdr);
710 	hdr->cmsg_level = SOL_ALG;
711 	hdr->cmsg_type = ALG_SET_IV;
712 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
713 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
714 	alg_iv->ivlen = iv_len;
715 	os_memcpy(alg_iv->iv, iv, iv_len);
716 
717 	ret = sendmsg(skcipher->t, &msg, 0);
718 	if (ret < 0) {
719 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
720 			   __func__, strerror(errno));
721 		linux_af_alg_skcipher_deinit(skcipher);
722 		return -1;
723 	}
724 
725 	ret = recvmsg(skcipher->t, &msg, 0);
726 	if (ret < 0) {
727 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
728 			   __func__, strerror(errno));
729 		linux_af_alg_skcipher_deinit(skcipher);
730 		return -1;
731 	}
732 	if ((size_t) ret < data_len) {
733 		wpa_printf(MSG_ERROR,
734 			   "%s: recvmsg not return full data (%d/%d)",
735 			   __func__, (int) ret, (int) data_len);
736 		linux_af_alg_skcipher_deinit(skcipher);
737 		return -1;
738 	}
739 
740 	linux_af_alg_skcipher_deinit(skcipher);
741 	return 0;
742 }
743 
744 
745 int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
746 {
747 	return aes_128_cbc_oper(key, 1, iv, data, data_len);
748 }
749 
750 
751 int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
752 {
753 	return aes_128_cbc_oper(key, 0, iv, data, data_len);
754 }
755 
756 
757 int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
758 		     const u8 *addr[], const size_t *len, u8 *mac)
759 {
760 	return linux_af_alg_hash_vector("cmac(aes)", key, key_len, num_elem,
761 					addr, len, mac, AES_BLOCK_SIZE);
762 }
763 
764 
765 int omac1_aes_128_vector(const u8 *key, size_t num_elem,
766 			 const u8 *addr[], const size_t *len, u8 *mac)
767 {
768 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
769 }
770 
771 
772 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
773 {
774 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
775 }
776 
777 
778 int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
779 {
780 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
781 }
782 
783 
784 int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
785 	       u8 *plain)
786 {
787 	struct linux_af_alg_skcipher *skcipher;
788 	char buf[100];
789 	struct iovec io[1];
790 	struct msghdr msg;
791 	struct cmsghdr *hdr;
792 	ssize_t ret;
793 	u32 *op;
794 	struct af_alg_iv *alg_iv;
795 	size_t iv_len = 8;
796 
797 	skcipher = linux_af_alg_skcipher("kw(aes)", kek, kek_len);
798 	if (!skcipher)
799 		return -1;
800 
801 	io[0].iov_base = (void *) (cipher + iv_len);
802 	io[0].iov_len = n * 8;
803 	os_memset(&msg, 0, sizeof(msg));
804 	os_memset(buf, 0, sizeof(buf));
805 	msg.msg_control = buf;
806 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
807 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
808 	msg.msg_iov = io;
809 	msg.msg_iovlen = 1;
810 
811 	hdr = CMSG_FIRSTHDR(&msg);
812 	hdr->cmsg_level = SOL_ALG;
813 	hdr->cmsg_type = ALG_SET_OP;
814 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
815 	op = (u32 *) CMSG_DATA(hdr);
816 	*op = ALG_OP_DECRYPT;
817 
818 	hdr = CMSG_NXTHDR(&msg, hdr);
819 	hdr->cmsg_level = SOL_ALG;
820 	hdr->cmsg_type = ALG_SET_IV;
821 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
822 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
823 	alg_iv->ivlen = iv_len;
824 	os_memcpy(alg_iv->iv, cipher, iv_len);
825 
826 	ret = sendmsg(skcipher->t, &msg, 0);
827 	if (ret < 0) {
828 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
829 			   __func__, strerror(errno));
830 		return -1;
831 	}
832 
833 	ret = read(skcipher->t, plain, n * 8);
834 	if (ret < 0) {
835 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
836 			   __func__, strerror(errno));
837 		linux_af_alg_skcipher_deinit(skcipher);
838 		return -1;
839 	}
840 	if (ret < n * 8) {
841 		wpa_printf(MSG_ERROR,
842 			   "%s: read not return full data (%d/%d)",
843 			   __func__, (int) ret, n * 8);
844 		linux_af_alg_skcipher_deinit(skcipher);
845 		return -1;
846 	}
847 
848 	linux_af_alg_skcipher_deinit(skcipher);
849 	return 0;
850 }
851 
852 
853 struct crypto_cipher {
854 	struct linux_af_alg_skcipher *skcipher;
855 };
856 
857 
858 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
859 					  const u8 *iv, const u8 *key,
860 					  size_t key_len)
861 {
862 	struct crypto_cipher *ctx;
863 	const char *name;
864 	struct af_alg_iv *alg_iv;
865 	size_t iv_len = 0;
866 	char buf[100];
867 	struct msghdr msg;
868 	struct cmsghdr *hdr;
869 	ssize_t ret;
870 
871 	ctx = os_zalloc(sizeof(*ctx));
872 	if (!ctx)
873 		return NULL;
874 
875 	switch (alg) {
876 	case CRYPTO_CIPHER_ALG_RC4:
877 		name = "ecb(arc4)";
878 		break;
879 	case CRYPTO_CIPHER_ALG_AES:
880 		name = "cbc(aes)";
881 		iv_len = AES_BLOCK_SIZE;
882 		break;
883 	case CRYPTO_CIPHER_ALG_3DES:
884 		name = "cbc(des3_ede)";
885 		iv_len = 8;
886 		break;
887 	case CRYPTO_CIPHER_ALG_DES:
888 		name = "cbc(des)";
889 		iv_len = 8;
890 		break;
891 	default:
892 		os_free(ctx);
893 		return NULL;
894 	}
895 
896 	ctx->skcipher = linux_af_alg_skcipher(name, key, key_len);
897 	if (!ctx->skcipher) {
898 		os_free(ctx);
899 		return NULL;
900 	}
901 
902 	if (iv && iv_len) {
903 		os_memset(&msg, 0, sizeof(msg));
904 		os_memset(buf, 0, sizeof(buf));
905 		msg.msg_control = buf;
906 		msg.msg_controllen = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
907 		hdr = CMSG_FIRSTHDR(&msg);
908 		hdr->cmsg_level = SOL_ALG;
909 		hdr->cmsg_type = ALG_SET_IV;
910 		hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
911 		alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
912 		alg_iv->ivlen = iv_len;
913 		os_memcpy(alg_iv->iv, iv, iv_len);
914 
915 		ret = sendmsg(ctx->skcipher->t, &msg, 0);
916 		if (ret < 0) {
917 			wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
918 				   __func__, strerror(errno));
919 			linux_af_alg_skcipher_deinit(ctx->skcipher);
920 			os_free(ctx);
921 			return NULL;
922 		}
923 	}
924 
925 	return ctx;
926 }
927 
928 
929 static int crypto_cipher_oper(struct crypto_cipher *ctx, u32 type, const u8 *in,
930 			      u8 *out, size_t len)
931 {
932 	char buf[CMSG_SPACE(sizeof(u32))];
933 	struct iovec io[1];
934 	struct msghdr msg;
935 	struct cmsghdr *hdr;
936 	ssize_t ret;
937 	u32 *op;
938 
939 	io[0].iov_base = (void *) in;
940 	io[0].iov_len = len;
941 	os_memset(&msg, 0, sizeof(msg));
942 	os_memset(buf, 0, sizeof(buf));
943 	msg.msg_control = buf;
944 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
945 	msg.msg_iov = io;
946 	msg.msg_iovlen = 1;
947 	hdr = CMSG_FIRSTHDR(&msg);
948 	hdr->cmsg_level = SOL_ALG;
949 	hdr->cmsg_type = ALG_SET_OP;
950 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
951 	op = (u32 *) CMSG_DATA(hdr);
952 	*op = type;
953 
954 	ret = sendmsg(ctx->skcipher->t, &msg, 0);
955 	if (ret < 0) {
956 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
957 			   __func__, strerror(errno));
958 		return -1;
959 	}
960 
961 	ret = read(ctx->skcipher->t, out, len);
962 	if (ret < 0) {
963 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
964 			   __func__, strerror(errno));
965 		return -1;
966 	}
967 	if (ret < (ssize_t) len) {
968 		wpa_printf(MSG_ERROR,
969 			   "%s: read did not return full data (%d/%d)",
970 			   __func__, (int) ret, (int) len);
971 		return -1;
972 	}
973 
974 	return 0;
975 }
976 
977 
978 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
979 			  u8 *crypt, size_t len)
980 {
981 	return crypto_cipher_oper(ctx, ALG_OP_ENCRYPT, plain, crypt, len);
982 }
983 
984 
985 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
986 			  u8 *plain, size_t len)
987 {
988 	return crypto_cipher_oper(ctx, ALG_OP_DECRYPT, crypt, plain, len);
989 }
990 
991 
992 void crypto_cipher_deinit(struct crypto_cipher *ctx)
993 {
994 	if (ctx) {
995 		linux_af_alg_skcipher_deinit(ctx->skcipher);
996 		os_free(ctx);
997 	}
998 }
999 
1000 
1001 int crypto_global_init(void)
1002 {
1003 	return 0;
1004 }
1005 
1006 
1007 void crypto_global_deinit(void)
1008 {
1009 }
1010