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
390	if (TEST_FAIL())
391		return -1;
392	return 0;
393}
394
395
396struct linux_af_alg_skcipher {
397	int s;
398	int t;
399};
400
401
402static 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
414static struct linux_af_alg_skcipher *
415linux_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;
442fail:
443	linux_af_alg_skcipher_deinit(skcipher);
444	return NULL;
445}
446
447
448static 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
497void * aes_encrypt_init(const u8 *key, size_t len)
498{
499	return linux_af_alg_skcipher("ecb(aes)", key, len);
500}
501
502
503int 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
511void aes_encrypt_deinit(void *ctx)
512{
513	linux_af_alg_skcipher_deinit(ctx);
514}
515
516
517void * aes_decrypt_init(const u8 *key, size_t len)
518{
519	return linux_af_alg_skcipher("ecb(aes)", key, len);
520}
521
522
523int 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
531void aes_decrypt_deinit(void *ctx)
532{
533	linux_af_alg_skcipher_deinit(ctx);
534}
535
536
537int 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
607int 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;
669fail:
670	linux_af_alg_skcipher_deinit(skcipher);
671	return res;
672}
673
674
675static 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
745int 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
751int 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
757int 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
765int 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
772int 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
778int 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
784int 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
853struct crypto_cipher {
854	struct linux_af_alg_skcipher *skcipher;
855};
856
857
858struct 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
929static 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
978int 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
985int 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
992void 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
1001int crypto_global_init(void)
1002{
1003	return 0;
1004}
1005
1006
1007void crypto_global_deinit(void)
1008{
1009}
1010