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
26static 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
57static 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;
117fail:
118	close(t);
119	close(s);
120
121	return ret;
122}
123
124
125int 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
132int 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
139int 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
147int 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
155int 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
163int 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
171int 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
179int 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
186int 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
194int 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
201int 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
209int 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
216int 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
224int 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
231struct crypto_hash {
232	int s;
233	int t;
234	size_t mac_len;
235	int failed;
236};
237
238
239struct 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
315void 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
340static void crypto_hash_deinit(struct crypto_hash *ctx)
341{
342	close(ctx->s);
343	close(ctx->t);
344	os_free(ctx);
345}
346
347
348int 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
393struct linux_af_alg_skcipher {
394	int s;
395	int t;
396};
397
398
399static 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
411static struct linux_af_alg_skcipher *
412linux_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;
439fail:
440	linux_af_alg_skcipher_deinit(skcipher);
441	return NULL;
442}
443
444
445static 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
494void * aes_encrypt_init(const u8 *key, size_t len)
495{
496	return linux_af_alg_skcipher("ecb(aes)", key, len);
497}
498
499
500int 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
508void aes_encrypt_deinit(void *ctx)
509{
510	linux_af_alg_skcipher_deinit(ctx);
511}
512
513
514void * aes_decrypt_init(const u8 *key, size_t len)
515{
516	return linux_af_alg_skcipher("ecb(aes)", key, len);
517}
518
519
520int 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
528void aes_decrypt_deinit(void *ctx)
529{
530	linux_af_alg_skcipher_deinit(ctx);
531}
532
533
534int 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
604int 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;
666fail:
667	linux_af_alg_skcipher_deinit(skcipher);
668	return res;
669}
670
671
672static 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
742int 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
748int 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
754int 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
762int 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
769int 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
775int 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
781int 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
850struct crypto_cipher {
851	struct linux_af_alg_skcipher *skcipher;
852};
853
854
855struct 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
926static 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
975int 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
982int 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
989void 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
998int crypto_global_init(void)
999{
1000	return 0;
1001}
1002
1003
1004void crypto_global_deinit(void)
1005{
1006}
1007