xref: /freebsd/contrib/wpa/src/crypto/crypto_linux.c (revision 0957b409)
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 }
1007