xref: /freebsd/contrib/wpa/src/crypto/crypto_linux.c (revision f9bc005b8ef3b507a5ecbc2d7fe4411ef70eff38)
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 		*len = ctx->mac_len;
367 		crypto_hash_deinit(ctx);
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 
584 	msg.msg_control = NULL;
585 	msg.msg_controllen = 0;
586 	ret = recvmsg(skcipher->t, &msg, 0);
587 	if (ret < 0) {
588 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
589 			   __func__, strerror(errno));
590 		os_free(skip_buf);
591 		linux_af_alg_skcipher_deinit(skcipher);
592 		return -1;
593 	}
594 	os_free(skip_buf);
595 	linux_af_alg_skcipher_deinit(skcipher);
596 
597 	if ((size_t) ret < skip + data_len) {
598 		wpa_printf(MSG_ERROR,
599 			   "%s: recvmsg did not return full data (%d/%d)",
600 			   __func__, (int) ret, (int) (skip + data_len));
601 		return -1;
602 	}
603 
604 	return 0;
605 }
606 
607 
608 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
609 {
610 	u8 pkey[8], next, tmp;
611 	int i;
612 	struct linux_af_alg_skcipher *skcipher;
613 	char buf[CMSG_SPACE(sizeof(u32))];
614 	struct iovec io[1];
615 	struct msghdr msg;
616 	struct cmsghdr *hdr;
617 	ssize_t ret;
618 	u32 *op;
619 	int res = -1;
620 
621 	/* Add parity bits to the key */
622 	next = 0;
623 	for (i = 0; i < 7; i++) {
624 		tmp = key[i];
625 		pkey[i] = (tmp >> i) | next | 1;
626 		next = tmp << (7 - i);
627 	}
628 	pkey[i] = next | 1;
629 
630 	skcipher = linux_af_alg_skcipher("ecb(des)", pkey, sizeof(pkey));
631 	if (!skcipher)
632 		goto fail;
633 
634 	io[0].iov_base = (void *) clear;
635 	io[0].iov_len = 8;
636 	os_memset(&msg, 0, sizeof(msg));
637 	os_memset(buf, 0, sizeof(buf));
638 	msg.msg_control = buf;
639 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
640 	msg.msg_iov = io;
641 	msg.msg_iovlen = 1;
642 	hdr = CMSG_FIRSTHDR(&msg);
643 	hdr->cmsg_level = SOL_ALG;
644 	hdr->cmsg_type = ALG_SET_OP;
645 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
646 	op = (u32 *) CMSG_DATA(hdr);
647 	*op = ALG_OP_ENCRYPT;
648 
649 	ret = sendmsg(skcipher->t, &msg, 0);
650 	if (ret < 0) {
651 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
652 			   __func__, strerror(errno));
653 		goto fail;
654 	}
655 
656 	ret = read(skcipher->t, cypher, 8);
657 	if (ret < 0) {
658 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
659 			   __func__, strerror(errno));
660 		goto fail;
661 	}
662 	if (ret < 8) {
663 		wpa_printf(MSG_ERROR,
664 			   "%s: read did not return full data (%d/8)",
665 			   __func__, (int) ret);
666 		goto fail;
667 	}
668 
669 	res = 0;
670 fail:
671 	linux_af_alg_skcipher_deinit(skcipher);
672 	return res;
673 }
674 
675 
676 static int aes_128_cbc_oper(const u8 *key, int enc, const u8 *iv,
677 			    u8 *data, size_t data_len)
678 {
679 	struct linux_af_alg_skcipher *skcipher;
680 	char buf[100];
681 	struct iovec io[1];
682 	struct msghdr msg;
683 	struct cmsghdr *hdr;
684 	ssize_t ret;
685 	u32 *op;
686 	struct af_alg_iv *alg_iv;
687 	size_t iv_len = AES_BLOCK_SIZE;
688 
689 	skcipher = linux_af_alg_skcipher("cbc(aes)", key, 16);
690 	if (!skcipher)
691 		return -1;
692 
693 	io[0].iov_base = (void *) data;
694 	io[0].iov_len = data_len;
695 	os_memset(&msg, 0, sizeof(msg));
696 	os_memset(buf, 0, sizeof(buf));
697 	msg.msg_control = buf;
698 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
699 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
700 	msg.msg_iov = io;
701 	msg.msg_iovlen = 1;
702 
703 	hdr = CMSG_FIRSTHDR(&msg);
704 	hdr->cmsg_level = SOL_ALG;
705 	hdr->cmsg_type = ALG_SET_OP;
706 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
707 	op = (u32 *) CMSG_DATA(hdr);
708 	*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
709 
710 	hdr = CMSG_NXTHDR(&msg, hdr);
711 	hdr->cmsg_level = SOL_ALG;
712 	hdr->cmsg_type = ALG_SET_IV;
713 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
714 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
715 	alg_iv->ivlen = iv_len;
716 	os_memcpy(alg_iv->iv, iv, iv_len);
717 
718 	ret = sendmsg(skcipher->t, &msg, 0);
719 	if (ret < 0) {
720 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
721 			   __func__, strerror(errno));
722 		linux_af_alg_skcipher_deinit(skcipher);
723 		return -1;
724 	}
725 
726 	ret = recvmsg(skcipher->t, &msg, 0);
727 	if (ret < 0) {
728 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
729 			   __func__, strerror(errno));
730 		linux_af_alg_skcipher_deinit(skcipher);
731 		return -1;
732 	}
733 	if ((size_t) ret < data_len) {
734 		wpa_printf(MSG_ERROR,
735 			   "%s: recvmsg not return full data (%d/%d)",
736 			   __func__, (int) ret, (int) data_len);
737 		linux_af_alg_skcipher_deinit(skcipher);
738 		return -1;
739 	}
740 
741 	linux_af_alg_skcipher_deinit(skcipher);
742 	return 0;
743 }
744 
745 
746 int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
747 {
748 	return aes_128_cbc_oper(key, 1, iv, data, data_len);
749 }
750 
751 
752 int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
753 {
754 	return aes_128_cbc_oper(key, 0, iv, data, data_len);
755 }
756 
757 
758 int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
759 		     const u8 *addr[], const size_t *len, u8 *mac)
760 {
761 	return linux_af_alg_hash_vector("cmac(aes)", key, key_len, num_elem,
762 					addr, len, mac, AES_BLOCK_SIZE);
763 }
764 
765 
766 int omac1_aes_128_vector(const u8 *key, size_t num_elem,
767 			 const u8 *addr[], const size_t *len, u8 *mac)
768 {
769 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
770 }
771 
772 
773 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
774 {
775 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
776 }
777 
778 
779 int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
780 {
781 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
782 }
783 
784 
785 int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
786 	       u8 *plain)
787 {
788 	struct linux_af_alg_skcipher *skcipher;
789 	char buf[100];
790 	struct iovec io[1];
791 	struct msghdr msg;
792 	struct cmsghdr *hdr;
793 	ssize_t ret;
794 	u32 *op;
795 	struct af_alg_iv *alg_iv;
796 	size_t iv_len = 8;
797 
798 	skcipher = linux_af_alg_skcipher("kw(aes)", kek, kek_len);
799 	if (!skcipher)
800 		return -1;
801 
802 	io[0].iov_base = (void *) (cipher + iv_len);
803 	io[0].iov_len = n * 8;
804 	os_memset(&msg, 0, sizeof(msg));
805 	os_memset(buf, 0, sizeof(buf));
806 	msg.msg_control = buf;
807 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
808 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
809 	msg.msg_iov = io;
810 	msg.msg_iovlen = 1;
811 
812 	hdr = CMSG_FIRSTHDR(&msg);
813 	hdr->cmsg_level = SOL_ALG;
814 	hdr->cmsg_type = ALG_SET_OP;
815 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
816 	op = (u32 *) CMSG_DATA(hdr);
817 	*op = ALG_OP_DECRYPT;
818 
819 	hdr = CMSG_NXTHDR(&msg, hdr);
820 	hdr->cmsg_level = SOL_ALG;
821 	hdr->cmsg_type = ALG_SET_IV;
822 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
823 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
824 	alg_iv->ivlen = iv_len;
825 	os_memcpy(alg_iv->iv, cipher, iv_len);
826 
827 	ret = sendmsg(skcipher->t, &msg, 0);
828 	if (ret < 0) {
829 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
830 			   __func__, strerror(errno));
831 		return -1;
832 	}
833 
834 	ret = read(skcipher->t, plain, n * 8);
835 	if (ret < 0) {
836 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
837 			   __func__, strerror(errno));
838 		linux_af_alg_skcipher_deinit(skcipher);
839 		return -1;
840 	}
841 	if (ret < n * 8) {
842 		wpa_printf(MSG_ERROR,
843 			   "%s: read not return full data (%d/%d)",
844 			   __func__, (int) ret, n * 8);
845 		linux_af_alg_skcipher_deinit(skcipher);
846 		return -1;
847 	}
848 
849 	linux_af_alg_skcipher_deinit(skcipher);
850 	return 0;
851 }
852 
853 
854 struct crypto_cipher {
855 	struct linux_af_alg_skcipher *skcipher;
856 };
857 
858 
859 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
860 					  const u8 *iv, const u8 *key,
861 					  size_t key_len)
862 {
863 	struct crypto_cipher *ctx;
864 	const char *name;
865 	struct af_alg_iv *alg_iv;
866 	size_t iv_len = 0;
867 	char buf[100];
868 	struct msghdr msg;
869 	struct cmsghdr *hdr;
870 	ssize_t ret;
871 
872 	ctx = os_zalloc(sizeof(*ctx));
873 	if (!ctx)
874 		return NULL;
875 
876 	switch (alg) {
877 	case CRYPTO_CIPHER_ALG_RC4:
878 		name = "ecb(arc4)";
879 		break;
880 	case CRYPTO_CIPHER_ALG_AES:
881 		name = "cbc(aes)";
882 		iv_len = AES_BLOCK_SIZE;
883 		break;
884 	case CRYPTO_CIPHER_ALG_3DES:
885 		name = "cbc(des3_ede)";
886 		iv_len = 8;
887 		break;
888 	case CRYPTO_CIPHER_ALG_DES:
889 		name = "cbc(des)";
890 		iv_len = 8;
891 		break;
892 	default:
893 		os_free(ctx);
894 		return NULL;
895 	}
896 
897 	ctx->skcipher = linux_af_alg_skcipher(name, key, key_len);
898 	if (!ctx->skcipher) {
899 		os_free(ctx);
900 		return NULL;
901 	}
902 
903 	if (iv && iv_len) {
904 		os_memset(&msg, 0, sizeof(msg));
905 		os_memset(buf, 0, sizeof(buf));
906 		msg.msg_control = buf;
907 		msg.msg_controllen = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
908 		hdr = CMSG_FIRSTHDR(&msg);
909 		hdr->cmsg_level = SOL_ALG;
910 		hdr->cmsg_type = ALG_SET_IV;
911 		hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
912 		alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
913 		alg_iv->ivlen = iv_len;
914 		os_memcpy(alg_iv->iv, iv, iv_len);
915 
916 		ret = sendmsg(ctx->skcipher->t, &msg, 0);
917 		if (ret < 0) {
918 			wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
919 				   __func__, strerror(errno));
920 			linux_af_alg_skcipher_deinit(ctx->skcipher);
921 			os_free(ctx);
922 			return NULL;
923 		}
924 	}
925 
926 	return ctx;
927 }
928 
929 
930 static int crypto_cipher_oper(struct crypto_cipher *ctx, u32 type, const u8 *in,
931 			      u8 *out, size_t len)
932 {
933 	char buf[CMSG_SPACE(sizeof(u32))];
934 	struct iovec io[1];
935 	struct msghdr msg;
936 	struct cmsghdr *hdr;
937 	ssize_t ret;
938 	u32 *op;
939 
940 	io[0].iov_base = (void *) in;
941 	io[0].iov_len = len;
942 	os_memset(&msg, 0, sizeof(msg));
943 	os_memset(buf, 0, sizeof(buf));
944 	msg.msg_control = buf;
945 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
946 	msg.msg_iov = io;
947 	msg.msg_iovlen = 1;
948 	hdr = CMSG_FIRSTHDR(&msg);
949 	hdr->cmsg_level = SOL_ALG;
950 	hdr->cmsg_type = ALG_SET_OP;
951 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
952 	op = (u32 *) CMSG_DATA(hdr);
953 	*op = type;
954 
955 	ret = sendmsg(ctx->skcipher->t, &msg, 0);
956 	if (ret < 0) {
957 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
958 			   __func__, strerror(errno));
959 		return -1;
960 	}
961 
962 	ret = read(ctx->skcipher->t, out, len);
963 	if (ret < 0) {
964 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
965 			   __func__, strerror(errno));
966 		return -1;
967 	}
968 	if (ret < (ssize_t) len) {
969 		wpa_printf(MSG_ERROR,
970 			   "%s: read did not return full data (%d/%d)",
971 			   __func__, (int) ret, (int) len);
972 		return -1;
973 	}
974 
975 	return 0;
976 }
977 
978 
979 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
980 			  u8 *crypt, size_t len)
981 {
982 	return crypto_cipher_oper(ctx, ALG_OP_ENCRYPT, plain, crypt, len);
983 }
984 
985 
986 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
987 			  u8 *plain, size_t len)
988 {
989 	return crypto_cipher_oper(ctx, ALG_OP_DECRYPT, crypt, plain, len);
990 }
991 
992 
993 void crypto_cipher_deinit(struct crypto_cipher *ctx)
994 {
995 	if (ctx) {
996 		linux_af_alg_skcipher_deinit(ctx->skcipher);
997 		os_free(ctx);
998 	}
999 }
1000 
1001 
1002 int crypto_global_init(void)
1003 {
1004 	return 0;
1005 }
1006 
1007 
1008 void crypto_global_deinit(void)
1009 {
1010 }
1011 
1012 
1013 void crypto_unload(void)
1014 {
1015 }
1016