Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Crypto wrapper for Linux kernel AF_ALG
      3  * Copyright (c) 2017, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 #include <linux/if_alg.h>
     11 
     12 #include "common.h"
     13 #include "crypto.h"
     14 #include "md5.h"
     15 #include "sha1.h"
     16 #include "sha256.h"
     17 #include "sha384.h"
     18 #include "aes.h"
     19 
     20 
     21 #ifndef SOL_ALG
     22 #define SOL_ALG 279
     23 #endif /* SOL_ALG */
     24 
     25 
     26 static int linux_af_alg_socket(const char *type, const char *name)
     27 {
     28 	struct sockaddr_alg sa;
     29 	int s;
     30 
     31 	if (TEST_FAIL())
     32 		return -1;
     33 
     34 	s = socket(AF_ALG, SOCK_SEQPACKET, 0);
     35 	if (s < 0) {
     36 		wpa_printf(MSG_ERROR, "%s: Failed to open AF_ALG socket: %s",
     37 			   __func__, strerror(errno));
     38 		return -1;
     39 	}
     40 
     41 	os_memset(&sa, 0, sizeof(sa));
     42 	sa.salg_family = AF_ALG;
     43 	os_strlcpy((char *) sa.salg_type, type, sizeof(sa.salg_type));
     44 	os_strlcpy((char *) sa.salg_name, name, sizeof(sa.salg_type));
     45 	if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
     46 		wpa_printf(MSG_ERROR,
     47 			   "%s: Failed to bind AF_ALG socket(%s,%s): %s",
     48 			   __func__, type, name, strerror(errno));
     49 		close(s);
     50 		return -1;
     51 	}
     52 
     53 	return s;
     54 }
     55 
     56 
     57 static int linux_af_alg_hash_vector(const char *alg, const u8 *key,
     58 				    size_t key_len, size_t num_elem,
     59 				    const u8 *addr[], const size_t *len,
     60 				    u8 *mac, size_t mac_len)
     61 {
     62 	int s, t;
     63 	size_t i;
     64 	ssize_t res;
     65 	int ret = -1;
     66 
     67 	s = linux_af_alg_socket("hash", alg);
     68 	if (s < 0)
     69 		return -1;
     70 
     71 	if (key && setsockopt(s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
     72 		wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
     73 			   __func__, strerror(errno));
     74 		close(s);
     75 		return -1;
     76 	}
     77 
     78 	t = accept(s, NULL, NULL);
     79 	if (t < 0) {
     80 		wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
     81 			   __func__, strerror(errno));
     82 		close(s);
     83 		return -1;
     84 	}
     85 
     86 	for (i = 0; i < num_elem; i++) {
     87 		res = send(t, addr[i], len[i], i + 1 < num_elem ? MSG_MORE : 0);
     88 		if (res < 0) {
     89 			wpa_printf(MSG_ERROR,
     90 				   "%s: send on AF_ALG socket failed: %s",
     91 				   __func__, strerror(errno));
     92 			goto fail;
     93 		}
     94 		if ((size_t) res < len[i]) {
     95 			wpa_printf(MSG_ERROR,
     96 				   "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
     97 				   __func__, (int) res, (int) len[i]);
     98 			goto fail;
     99 		}
    100 	}
    101 
    102 	res = recv(t, mac, mac_len, 0);
    103 	if (res < 0) {
    104 		wpa_printf(MSG_ERROR,
    105 			   "%s: recv on AF_ALG socket failed: %s",
    106 			   __func__, strerror(errno));
    107 		goto fail;
    108 	}
    109 	if ((size_t) res < mac_len) {
    110 		wpa_printf(MSG_ERROR,
    111 			   "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
    112 			   __func__, (int) res, (int) mac_len);
    113 		goto fail;
    114 	}
    115 
    116 	ret = 0;
    117 fail:
    118 	close(t);
    119 	close(s);
    120 
    121 	return ret;
    122 }
    123 
    124 
    125 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
    126 {
    127 	return linux_af_alg_hash_vector("md4", NULL, 0, num_elem, addr, len,
    128 					mac, 16);
    129 }
    130 
    131 
    132 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
    133 {
    134 	return linux_af_alg_hash_vector("md5", NULL, 0, num_elem, addr, len,
    135 					mac, MD5_MAC_LEN);
    136 }
    137 
    138 
    139 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
    140 		u8 *mac)
    141 {
    142 	return linux_af_alg_hash_vector("sha1", NULL, 0, num_elem, addr, len,
    143 					mac, SHA1_MAC_LEN);
    144 }
    145 
    146 
    147 int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
    148 		  u8 *mac)
    149 {
    150 	return linux_af_alg_hash_vector("sha256", NULL, 0, num_elem, addr, len,
    151 					mac, SHA256_MAC_LEN);
    152 }
    153 
    154 
    155 int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
    156 		  u8 *mac)
    157 {
    158 	return linux_af_alg_hash_vector("sha384", NULL, 0, num_elem, addr, len,
    159 					mac, SHA384_MAC_LEN);
    160 }
    161 
    162 
    163 int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
    164 		  u8 *mac)
    165 {
    166 	return linux_af_alg_hash_vector("sha512", NULL, 0, num_elem, addr, len,
    167 					mac, 64);
    168 }
    169 
    170 
    171 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
    172 		    const u8 *addr[], const size_t *len, u8 *mac)
    173 {
    174 	return linux_af_alg_hash_vector("hmac(md5)", key, key_len, num_elem,
    175 					addr, len, mac, 16);
    176 }
    177 
    178 
    179 int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
    180 	     u8 *mac)
    181 {
    182 	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
    183 }
    184 
    185 
    186 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
    187 		     const u8 *addr[], const size_t *len, u8 *mac)
    188 {
    189 	return linux_af_alg_hash_vector("hmac(sha1)", key, key_len, num_elem,
    190 					addr, len, mac, SHA1_MAC_LEN);
    191 }
    192 
    193 
    194 int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
    195 	      u8 *mac)
    196 {
    197 	return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
    198 }
    199 
    200 
    201 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
    202 		       const u8 *addr[], const size_t *len, u8 *mac)
    203 {
    204 	return linux_af_alg_hash_vector("hmac(sha256)", key, key_len, num_elem,
    205 					addr, len, mac, SHA256_MAC_LEN);
    206 }
    207 
    208 
    209 int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
    210 		size_t data_len, u8 *mac)
    211 {
    212 	return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
    213 }
    214 
    215 
    216 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
    217 		       const u8 *addr[], const size_t *len, u8 *mac)
    218 {
    219 	return linux_af_alg_hash_vector("hmac(sha384)", key, key_len, num_elem,
    220 					addr, len, mac, SHA384_MAC_LEN);
    221 }
    222 
    223 
    224 int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
    225 		size_t data_len, u8 *mac)
    226 {
    227 	return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
    228 }
    229 
    230 
    231 struct crypto_hash {
    232 	int s;
    233 	int t;
    234 	size_t mac_len;
    235 	int failed;
    236 };
    237 
    238 
    239 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
    240 				      size_t key_len)
    241 {
    242 	struct crypto_hash *ctx;
    243 	const char *name;
    244 
    245 	ctx = os_zalloc(sizeof(*ctx));
    246 	if (!ctx)
    247 		return NULL;
    248 
    249 	switch (alg) {
    250 	case CRYPTO_HASH_ALG_MD5:
    251 		name = "md5";
    252 		ctx->mac_len = MD5_MAC_LEN;
    253 		break;
    254 	case CRYPTO_HASH_ALG_SHA1:
    255 		name = "sha1";
    256 		ctx->mac_len = SHA1_MAC_LEN;
    257 		break;
    258 	case CRYPTO_HASH_ALG_HMAC_MD5:
    259 		name = "hmac(md5)";
    260 		ctx->mac_len = MD5_MAC_LEN;
    261 		break;
    262 	case CRYPTO_HASH_ALG_HMAC_SHA1:
    263 		name = "hmac(sha1)";
    264 		ctx->mac_len = SHA1_MAC_LEN;
    265 		break;
    266 	case CRYPTO_HASH_ALG_SHA256:
    267 		name = "sha256";
    268 		ctx->mac_len = SHA256_MAC_LEN;
    269 		break;
    270 	case CRYPTO_HASH_ALG_HMAC_SHA256:
    271 		name = "hmac(sha256)";
    272 		ctx->mac_len = SHA256_MAC_LEN;
    273 		break;
    274 	case CRYPTO_HASH_ALG_SHA384:
    275 		name = "sha384";
    276 		ctx->mac_len = SHA384_MAC_LEN;
    277 		break;
    278 	case CRYPTO_HASH_ALG_SHA512:
    279 		name = "sha512";
    280 		ctx->mac_len = 64;
    281 		break;
    282 	default:
    283 		os_free(ctx);
    284 		return NULL;
    285 	}
    286 
    287 	ctx->s = linux_af_alg_socket("hash", name);
    288 	if (ctx->s < 0) {
    289 		os_free(ctx);
    290 		return NULL;
    291 	}
    292 
    293 	if (key && key_len &&
    294 	    setsockopt(ctx->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
    295 		wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
    296 			   __func__, strerror(errno));
    297 		close(ctx->s);
    298 		os_free(ctx);
    299 		return NULL;
    300 	}
    301 
    302 	ctx->t = accept(ctx->s, NULL, NULL);
    303 	if (ctx->t < 0) {
    304 		wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
    305 			   __func__, strerror(errno));
    306 		close(ctx->s);
    307 		os_free(ctx);
    308 		return NULL;
    309 	}
    310 
    311 	return ctx;
    312 }
    313 
    314 
    315 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
    316 {
    317 	ssize_t res;
    318 
    319 	if (!ctx)
    320 		return;
    321 
    322 	res = send(ctx->t, data, len, MSG_MORE);
    323 	if (res < 0) {
    324 		wpa_printf(MSG_ERROR,
    325 			   "%s: send on AF_ALG socket failed: %s",
    326 			   __func__, strerror(errno));
    327 		ctx->failed = 1;
    328 		return;
    329 	}
    330 	if ((size_t) res < len) {
    331 		wpa_printf(MSG_ERROR,
    332 			   "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
    333 			   __func__, (int) res, (int) len);
    334 		ctx->failed = 1;
    335 		return;
    336 	}
    337 }
    338 
    339 
    340 static void crypto_hash_deinit(struct crypto_hash *ctx)
    341 {
    342 	close(ctx->s);
    343 	close(ctx->t);
    344 	os_free(ctx);
    345 }
    346 
    347 
    348 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
    349 {
    350 	ssize_t res;
    351 
    352 	if (!ctx)
    353 		return -2;
    354 
    355 	if (!mac || !len) {
    356 		crypto_hash_deinit(ctx);
    357 		return 0;
    358 	}
    359 
    360 	if (ctx->failed) {
    361 		crypto_hash_deinit(ctx);
    362 		return -2;
    363 	}
    364 
    365 	if (*len < ctx->mac_len) {
    366 		crypto_hash_deinit(ctx);
    367 		*len = ctx->mac_len;
    368 		return -1;
    369 	}
    370 	*len = ctx->mac_len;
    371 
    372 	res = recv(ctx->t, mac, ctx->mac_len, 0);
    373 	if (res < 0) {
    374 		wpa_printf(MSG_ERROR,
    375 			   "%s: recv on AF_ALG socket failed: %s",
    376 			   __func__, strerror(errno));
    377 		crypto_hash_deinit(ctx);
    378 		return -2;
    379 	}
    380 	if ((size_t) res < ctx->mac_len) {
    381 		wpa_printf(MSG_ERROR,
    382 			   "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
    383 			   __func__, (int) res, (int) ctx->mac_len);
    384 		crypto_hash_deinit(ctx);
    385 		return -2;
    386 	}
    387 
    388 	crypto_hash_deinit(ctx);
    389 
    390 	if (TEST_FAIL())
    391 		return -1;
    392 	return 0;
    393 }
    394 
    395 
    396 struct linux_af_alg_skcipher {
    397 	int s;
    398 	int t;
    399 };
    400 
    401 
    402 static void linux_af_alg_skcipher_deinit(struct linux_af_alg_skcipher *skcipher)
    403 {
    404 	if (!skcipher)
    405 		return;
    406 	if (skcipher->s >= 0)
    407 		close(skcipher->s);
    408 	if (skcipher->t >= 0)
    409 		close(skcipher->t);
    410 	os_free(skcipher);
    411 }
    412 
    413 
    414 static struct linux_af_alg_skcipher *
    415 linux_af_alg_skcipher(const char *alg, const u8 *key, size_t key_len)
    416 {
    417 	struct linux_af_alg_skcipher *skcipher;
    418 
    419 	skcipher = os_zalloc(sizeof(*skcipher));
    420 	if (!skcipher)
    421 		goto fail;
    422 	skcipher->t = -1;
    423 
    424 	skcipher->s = linux_af_alg_socket("skcipher", alg);
    425 	if (skcipher->s < 0)
    426 		goto fail;
    427 
    428 	if (setsockopt(skcipher->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
    429 		wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
    430 			   __func__, strerror(errno));
    431 		goto fail;
    432 	}
    433 
    434 	skcipher->t = accept(skcipher->s, NULL, NULL);
    435 	if (skcipher->t < 0) {
    436 		wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
    437 			   __func__, strerror(errno));
    438 		goto fail;
    439 	}
    440 
    441 	return skcipher;
    442 fail:
    443 	linux_af_alg_skcipher_deinit(skcipher);
    444 	return NULL;
    445 }
    446 
    447 
    448 static int linux_af_alg_skcipher_oper(struct linux_af_alg_skcipher *skcipher,
    449 				      int enc, const u8 *in, u8 *out)
    450 {
    451 	char buf[CMSG_SPACE(sizeof(u32))];
    452 	struct iovec io[1];
    453 	struct msghdr msg;
    454 	struct cmsghdr *hdr;
    455 	ssize_t ret;
    456 	u32 *op;
    457 
    458 	io[0].iov_base = (void *) in;
    459 	io[0].iov_len = AES_BLOCK_SIZE;
    460 	os_memset(&msg, 0, sizeof(msg));
    461 	os_memset(buf, 0, sizeof(buf));
    462 	msg.msg_control = buf;
    463 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
    464 	msg.msg_iov = io;
    465 	msg.msg_iovlen = 1;
    466 	hdr = CMSG_FIRSTHDR(&msg);
    467 	hdr->cmsg_level = SOL_ALG;
    468 	hdr->cmsg_type = ALG_SET_OP;
    469 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    470 	op = (u32 *) CMSG_DATA(hdr);
    471 	*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
    472 
    473 	ret = sendmsg(skcipher->t, &msg, 0);
    474 	if (ret < 0) {
    475 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    476 			   __func__, strerror(errno));
    477 		return -1;
    478 	}
    479 
    480 	ret = read(skcipher->t, out, AES_BLOCK_SIZE);
    481 	if (ret < 0) {
    482 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
    483 			   __func__, strerror(errno));
    484 		return -1;
    485 	}
    486 	if (ret < AES_BLOCK_SIZE) {
    487 		wpa_printf(MSG_ERROR,
    488 			   "%s: read did not return full data (%d/%d)",
    489 			   __func__, (int) ret, AES_BLOCK_SIZE);
    490 		return -1;
    491 	}
    492 
    493 	return 0;
    494 }
    495 
    496 
    497 void * aes_encrypt_init(const u8 *key, size_t len)
    498 {
    499 	return linux_af_alg_skcipher("ecb(aes)", key, len);
    500 }
    501 
    502 
    503 int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
    504 {
    505 	struct linux_af_alg_skcipher *skcipher = ctx;
    506 
    507 	return linux_af_alg_skcipher_oper(skcipher, 1, plain, crypt);
    508 }
    509 
    510 
    511 void aes_encrypt_deinit(void *ctx)
    512 {
    513 	linux_af_alg_skcipher_deinit(ctx);
    514 }
    515 
    516 
    517 void * aes_decrypt_init(const u8 *key, size_t len)
    518 {
    519 	return linux_af_alg_skcipher("ecb(aes)", key, len);
    520 }
    521 
    522 
    523 int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
    524 {
    525 	struct linux_af_alg_skcipher *skcipher = ctx;
    526 
    527 	return linux_af_alg_skcipher_oper(skcipher, 0, crypt, plain);
    528 }
    529 
    530 
    531 void aes_decrypt_deinit(void *ctx)
    532 {
    533 	linux_af_alg_skcipher_deinit(ctx);
    534 }
    535 
    536 
    537 int rc4_skip(const u8 *key, size_t keylen, size_t skip,
    538 	     u8 *data, size_t data_len)
    539 {
    540 	struct linux_af_alg_skcipher *skcipher;
    541 	u8 *skip_buf;
    542 	char buf[CMSG_SPACE(sizeof(u32))];
    543 	struct iovec io[2];
    544 	struct msghdr msg;
    545 	struct cmsghdr *hdr;
    546 	ssize_t ret;
    547 	u32 *op;
    548 
    549 	skip_buf = os_zalloc(skip + 1);
    550 	if (!skip_buf)
    551 		return -1;
    552 	skcipher = linux_af_alg_skcipher("ecb(arc4)", key, keylen);
    553 	if (!skcipher) {
    554 		os_free(skip_buf);
    555 		return -1;
    556 	}
    557 
    558 	io[0].iov_base = skip_buf;
    559 	io[0].iov_len = skip;
    560 	io[1].iov_base = data;
    561 	io[1].iov_len = data_len;
    562 	os_memset(&msg, 0, sizeof(msg));
    563 	os_memset(buf, 0, sizeof(buf));
    564 	msg.msg_control = buf;
    565 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
    566 	msg.msg_iov = io;
    567 	msg.msg_iovlen = 2;
    568 	hdr = CMSG_FIRSTHDR(&msg);
    569 	hdr->cmsg_level = SOL_ALG;
    570 	hdr->cmsg_type = ALG_SET_OP;
    571 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    572 	op = (u32 *) CMSG_DATA(hdr);
    573 	*op = ALG_OP_ENCRYPT;
    574 
    575 	ret = sendmsg(skcipher->t, &msg, 0);
    576 	if (ret < 0) {
    577 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    578 			   __func__, strerror(errno));
    579 		os_free(skip_buf);
    580 		linux_af_alg_skcipher_deinit(skcipher);
    581 		return -1;
    582 	}
    583 	os_free(skip_buf);
    584 
    585 	msg.msg_control = NULL;
    586 	msg.msg_controllen = 0;
    587 	ret = recvmsg(skcipher->t, &msg, 0);
    588 	if (ret < 0) {
    589 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
    590 			   __func__, strerror(errno));
    591 		linux_af_alg_skcipher_deinit(skcipher);
    592 		return -1;
    593 	}
    594 	linux_af_alg_skcipher_deinit(skcipher);
    595 
    596 	if ((size_t) ret < skip + data_len) {
    597 		wpa_printf(MSG_ERROR,
    598 			   "%s: recvmsg did not return full data (%d/%d)",
    599 			   __func__, (int) ret, (int) (skip + data_len));
    600 		return -1;
    601 	}
    602 
    603 	return 0;
    604 }
    605 
    606 
    607 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
    608 {
    609 	u8 pkey[8], next, tmp;
    610 	int i;
    611 	struct linux_af_alg_skcipher *skcipher;
    612 	char buf[CMSG_SPACE(sizeof(u32))];
    613 	struct iovec io[1];
    614 	struct msghdr msg;
    615 	struct cmsghdr *hdr;
    616 	ssize_t ret;
    617 	u32 *op;
    618 	int res = -1;
    619 
    620 	/* Add parity bits to the key */
    621 	next = 0;
    622 	for (i = 0; i < 7; i++) {
    623 		tmp = key[i];
    624 		pkey[i] = (tmp >> i) | next | 1;
    625 		next = tmp << (7 - i);
    626 	}
    627 	pkey[i] = next | 1;
    628 
    629 	skcipher = linux_af_alg_skcipher("ecb(des)", pkey, sizeof(pkey));
    630 	if (!skcipher)
    631 		goto fail;
    632 
    633 	io[0].iov_base = (void *) clear;
    634 	io[0].iov_len = 8;
    635 	os_memset(&msg, 0, sizeof(msg));
    636 	os_memset(buf, 0, sizeof(buf));
    637 	msg.msg_control = buf;
    638 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
    639 	msg.msg_iov = io;
    640 	msg.msg_iovlen = 1;
    641 	hdr = CMSG_FIRSTHDR(&msg);
    642 	hdr->cmsg_level = SOL_ALG;
    643 	hdr->cmsg_type = ALG_SET_OP;
    644 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    645 	op = (u32 *) CMSG_DATA(hdr);
    646 	*op = ALG_OP_ENCRYPT;
    647 
    648 	ret = sendmsg(skcipher->t, &msg, 0);
    649 	if (ret < 0) {
    650 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    651 			   __func__, strerror(errno));
    652 		goto fail;
    653 	}
    654 
    655 	ret = read(skcipher->t, cypher, 8);
    656 	if (ret < 0) {
    657 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
    658 			   __func__, strerror(errno));
    659 		goto fail;
    660 	}
    661 	if (ret < 8) {
    662 		wpa_printf(MSG_ERROR,
    663 			   "%s: read did not return full data (%d/8)",
    664 			   __func__, (int) ret);
    665 		goto fail;
    666 	}
    667 
    668 	res = 0;
    669 fail:
    670 	linux_af_alg_skcipher_deinit(skcipher);
    671 	return res;
    672 }
    673 
    674 
    675 static int aes_128_cbc_oper(const u8 *key, int enc, const u8 *iv,
    676 			    u8 *data, size_t data_len)
    677 {
    678 	struct linux_af_alg_skcipher *skcipher;
    679 	char buf[100];
    680 	struct iovec io[1];
    681 	struct msghdr msg;
    682 	struct cmsghdr *hdr;
    683 	ssize_t ret;
    684 	u32 *op;
    685 	struct af_alg_iv *alg_iv;
    686 	size_t iv_len = AES_BLOCK_SIZE;
    687 
    688 	skcipher = linux_af_alg_skcipher("cbc(aes)", key, 16);
    689 	if (!skcipher)
    690 		return -1;
    691 
    692 	io[0].iov_base = (void *) data;
    693 	io[0].iov_len = data_len;
    694 	os_memset(&msg, 0, sizeof(msg));
    695 	os_memset(buf, 0, sizeof(buf));
    696 	msg.msg_control = buf;
    697 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
    698 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    699 	msg.msg_iov = io;
    700 	msg.msg_iovlen = 1;
    701 
    702 	hdr = CMSG_FIRSTHDR(&msg);
    703 	hdr->cmsg_level = SOL_ALG;
    704 	hdr->cmsg_type = ALG_SET_OP;
    705 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    706 	op = (u32 *) CMSG_DATA(hdr);
    707 	*op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
    708 
    709 	hdr = CMSG_NXTHDR(&msg, hdr);
    710 	hdr->cmsg_level = SOL_ALG;
    711 	hdr->cmsg_type = ALG_SET_IV;
    712 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    713 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
    714 	alg_iv->ivlen = iv_len;
    715 	os_memcpy(alg_iv->iv, iv, iv_len);
    716 
    717 	ret = sendmsg(skcipher->t, &msg, 0);
    718 	if (ret < 0) {
    719 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    720 			   __func__, strerror(errno));
    721 		linux_af_alg_skcipher_deinit(skcipher);
    722 		return -1;
    723 	}
    724 
    725 	ret = recvmsg(skcipher->t, &msg, 0);
    726 	if (ret < 0) {
    727 		wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
    728 			   __func__, strerror(errno));
    729 		linux_af_alg_skcipher_deinit(skcipher);
    730 		return -1;
    731 	}
    732 	if ((size_t) ret < data_len) {
    733 		wpa_printf(MSG_ERROR,
    734 			   "%s: recvmsg not return full data (%d/%d)",
    735 			   __func__, (int) ret, (int) data_len);
    736 		linux_af_alg_skcipher_deinit(skcipher);
    737 		return -1;
    738 	}
    739 
    740 	linux_af_alg_skcipher_deinit(skcipher);
    741 	return 0;
    742 }
    743 
    744 
    745 int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
    746 {
    747 	return aes_128_cbc_oper(key, 1, iv, data, data_len);
    748 }
    749 
    750 
    751 int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
    752 {
    753 	return aes_128_cbc_oper(key, 0, iv, data, data_len);
    754 }
    755 
    756 
    757 int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
    758 		     const u8 *addr[], const size_t *len, u8 *mac)
    759 {
    760 	return linux_af_alg_hash_vector("cmac(aes)", key, key_len, num_elem,
    761 					addr, len, mac, AES_BLOCK_SIZE);
    762 }
    763 
    764 
    765 int omac1_aes_128_vector(const u8 *key, size_t num_elem,
    766 			 const u8 *addr[], const size_t *len, u8 *mac)
    767 {
    768 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
    769 }
    770 
    771 
    772 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
    773 {
    774 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
    775 }
    776 
    777 
    778 int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
    779 {
    780 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
    781 }
    782 
    783 
    784 int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
    785 	       u8 *plain)
    786 {
    787 	struct linux_af_alg_skcipher *skcipher;
    788 	char buf[100];
    789 	struct iovec io[1];
    790 	struct msghdr msg;
    791 	struct cmsghdr *hdr;
    792 	ssize_t ret;
    793 	u32 *op;
    794 	struct af_alg_iv *alg_iv;
    795 	size_t iv_len = 8;
    796 
    797 	skcipher = linux_af_alg_skcipher("kw(aes)", kek, kek_len);
    798 	if (!skcipher)
    799 		return -1;
    800 
    801 	io[0].iov_base = (void *) (cipher + iv_len);
    802 	io[0].iov_len = n * 8;
    803 	os_memset(&msg, 0, sizeof(msg));
    804 	os_memset(buf, 0, sizeof(buf));
    805 	msg.msg_control = buf;
    806 	msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
    807 		CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    808 	msg.msg_iov = io;
    809 	msg.msg_iovlen = 1;
    810 
    811 	hdr = CMSG_FIRSTHDR(&msg);
    812 	hdr->cmsg_level = SOL_ALG;
    813 	hdr->cmsg_type = ALG_SET_OP;
    814 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    815 	op = (u32 *) CMSG_DATA(hdr);
    816 	*op = ALG_OP_DECRYPT;
    817 
    818 	hdr = CMSG_NXTHDR(&msg, hdr);
    819 	hdr->cmsg_level = SOL_ALG;
    820 	hdr->cmsg_type = ALG_SET_IV;
    821 	hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    822 	alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
    823 	alg_iv->ivlen = iv_len;
    824 	os_memcpy(alg_iv->iv, cipher, iv_len);
    825 
    826 	ret = sendmsg(skcipher->t, &msg, 0);
    827 	if (ret < 0) {
    828 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    829 			   __func__, strerror(errno));
    830 		return -1;
    831 	}
    832 
    833 	ret = read(skcipher->t, plain, n * 8);
    834 	if (ret < 0) {
    835 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
    836 			   __func__, strerror(errno));
    837 		linux_af_alg_skcipher_deinit(skcipher);
    838 		return -1;
    839 	}
    840 	if (ret < n * 8) {
    841 		wpa_printf(MSG_ERROR,
    842 			   "%s: read not return full data (%d/%d)",
    843 			   __func__, (int) ret, n * 8);
    844 		linux_af_alg_skcipher_deinit(skcipher);
    845 		return -1;
    846 	}
    847 
    848 	linux_af_alg_skcipher_deinit(skcipher);
    849 	return 0;
    850 }
    851 
    852 
    853 struct crypto_cipher {
    854 	struct linux_af_alg_skcipher *skcipher;
    855 };
    856 
    857 
    858 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
    859 					  const u8 *iv, const u8 *key,
    860 					  size_t key_len)
    861 {
    862 	struct crypto_cipher *ctx;
    863 	const char *name;
    864 	struct af_alg_iv *alg_iv;
    865 	size_t iv_len = 0;
    866 	char buf[100];
    867 	struct msghdr msg;
    868 	struct cmsghdr *hdr;
    869 	ssize_t ret;
    870 
    871 	ctx = os_zalloc(sizeof(*ctx));
    872 	if (!ctx)
    873 		return NULL;
    874 
    875 	switch (alg) {
    876 	case CRYPTO_CIPHER_ALG_RC4:
    877 		name = "ecb(arc4)";
    878 		break;
    879 	case CRYPTO_CIPHER_ALG_AES:
    880 		name = "cbc(aes)";
    881 		iv_len = AES_BLOCK_SIZE;
    882 		break;
    883 	case CRYPTO_CIPHER_ALG_3DES:
    884 		name = "cbc(des3_ede)";
    885 		iv_len = 8;
    886 		break;
    887 	case CRYPTO_CIPHER_ALG_DES:
    888 		name = "cbc(des)";
    889 		iv_len = 8;
    890 		break;
    891 	default:
    892 		os_free(ctx);
    893 		return NULL;
    894 	}
    895 
    896 	ctx->skcipher = linux_af_alg_skcipher(name, key, key_len);
    897 	if (!ctx->skcipher) {
    898 		os_free(ctx);
    899 		return NULL;
    900 	}
    901 
    902 	if (iv && iv_len) {
    903 		os_memset(&msg, 0, sizeof(msg));
    904 		os_memset(buf, 0, sizeof(buf));
    905 		msg.msg_control = buf;
    906 		msg.msg_controllen = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    907 		hdr = CMSG_FIRSTHDR(&msg);
    908 		hdr->cmsg_level = SOL_ALG;
    909 		hdr->cmsg_type = ALG_SET_IV;
    910 		hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
    911 		alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
    912 		alg_iv->ivlen = iv_len;
    913 		os_memcpy(alg_iv->iv, iv, iv_len);
    914 
    915 		ret = sendmsg(ctx->skcipher->t, &msg, 0);
    916 		if (ret < 0) {
    917 			wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    918 				   __func__, strerror(errno));
    919 			linux_af_alg_skcipher_deinit(ctx->skcipher);
    920 			os_free(ctx);
    921 			return NULL;
    922 		}
    923 	}
    924 
    925 	return ctx;
    926 }
    927 
    928 
    929 static int crypto_cipher_oper(struct crypto_cipher *ctx, u32 type, const u8 *in,
    930 			      u8 *out, size_t len)
    931 {
    932 	char buf[CMSG_SPACE(sizeof(u32))];
    933 	struct iovec io[1];
    934 	struct msghdr msg;
    935 	struct cmsghdr *hdr;
    936 	ssize_t ret;
    937 	u32 *op;
    938 
    939 	io[0].iov_base = (void *) in;
    940 	io[0].iov_len = len;
    941 	os_memset(&msg, 0, sizeof(msg));
    942 	os_memset(buf, 0, sizeof(buf));
    943 	msg.msg_control = buf;
    944 	msg.msg_controllen = CMSG_SPACE(sizeof(u32));
    945 	msg.msg_iov = io;
    946 	msg.msg_iovlen = 1;
    947 	hdr = CMSG_FIRSTHDR(&msg);
    948 	hdr->cmsg_level = SOL_ALG;
    949 	hdr->cmsg_type = ALG_SET_OP;
    950 	hdr->cmsg_len = CMSG_LEN(sizeof(u32));
    951 	op = (u32 *) CMSG_DATA(hdr);
    952 	*op = type;
    953 
    954 	ret = sendmsg(ctx->skcipher->t, &msg, 0);
    955 	if (ret < 0) {
    956 		wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
    957 			   __func__, strerror(errno));
    958 		return -1;
    959 	}
    960 
    961 	ret = read(ctx->skcipher->t, out, len);
    962 	if (ret < 0) {
    963 		wpa_printf(MSG_ERROR, "%s: read failed: %s",
    964 			   __func__, strerror(errno));
    965 		return -1;
    966 	}
    967 	if (ret < (ssize_t) len) {
    968 		wpa_printf(MSG_ERROR,
    969 			   "%s: read did not return full data (%d/%d)",
    970 			   __func__, (int) ret, (int) len);
    971 		return -1;
    972 	}
    973 
    974 	return 0;
    975 }
    976 
    977 
    978 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
    979 			  u8 *crypt, size_t len)
    980 {
    981 	return crypto_cipher_oper(ctx, ALG_OP_ENCRYPT, plain, crypt, len);
    982 }
    983 
    984 
    985 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
    986 			  u8 *plain, size_t len)
    987 {
    988 	return crypto_cipher_oper(ctx, ALG_OP_DECRYPT, crypt, plain, len);
    989 }
    990 
    991 
    992 void crypto_cipher_deinit(struct crypto_cipher *ctx)
    993 {
    994 	if (ctx) {
    995 		linux_af_alg_skcipher_deinit(ctx->skcipher);
    996 		os_free(ctx);
    997 	}
    998 }
    999 
   1000 
   1001 int crypto_global_init(void)
   1002 {
   1003 	return 0;
   1004 }
   1005 
   1006 
   1007 void crypto_global_deinit(void)
   1008 {
   1009 }
   1010