vendor/wpa_supplicant: upgrade from 2.1 to 2.9
[dragonfly.git] / contrib / wpa_supplicant / src / crypto / crypto_linux.c
1 /*
2  * Crypto wrapper for Linux kernel AF_ALG
3  * Copyright (c) 2017, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10 #include <linux/if_alg.h>
11
12 #include "common.h"
13 #include "crypto.h"
14 #include "md5.h"
15 #include "sha1.h"
16 #include "sha256.h"
17 #include "sha384.h"
18 #include "aes.h"
19
20
21 #ifndef SOL_ALG
22 #define SOL_ALG 279
23 #endif /* SOL_ALG */
24
25
26 static int linux_af_alg_socket(const char *type, const char *name)
27 {
28         struct sockaddr_alg sa;
29         int s;
30
31         if (TEST_FAIL())
32                 return -1;
33
34         s = socket(AF_ALG, SOCK_SEQPACKET, 0);
35         if (s < 0) {
36                 wpa_printf(MSG_ERROR, "%s: Failed to open AF_ALG socket: %s",
37                            __func__, strerror(errno));
38                 return -1;
39         }
40
41         os_memset(&sa, 0, sizeof(sa));
42         sa.salg_family = AF_ALG;
43         os_strlcpy((char *) sa.salg_type, type, sizeof(sa.salg_type));
44         os_strlcpy((char *) sa.salg_name, name, sizeof(sa.salg_type));
45         if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
46                 wpa_printf(MSG_ERROR,
47                            "%s: Failed to bind AF_ALG socket(%s,%s): %s",
48                            __func__, type, name, strerror(errno));
49                 close(s);
50                 return -1;
51         }
52
53         return s;
54 }
55
56
57 static int linux_af_alg_hash_vector(const char *alg, const u8 *key,
58                                     size_t key_len, size_t num_elem,
59                                     const u8 *addr[], const size_t *len,
60                                     u8 *mac, size_t mac_len)
61 {
62         int s, t;
63         size_t i;
64         ssize_t res;
65         int ret = -1;
66
67         s = linux_af_alg_socket("hash", alg);
68         if (s < 0)
69                 return -1;
70
71         if (key && setsockopt(s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
72                 wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
73                            __func__, strerror(errno));
74                 close(s);
75                 return -1;
76         }
77
78         t = accept(s, NULL, NULL);
79         if (t < 0) {
80                 wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
81                            __func__, strerror(errno));
82                 close(s);
83                 return -1;
84         }
85
86         for (i = 0; i < num_elem; i++) {
87                 res = send(t, addr[i], len[i], i + 1 < num_elem ? MSG_MORE : 0);
88                 if (res < 0) {
89                         wpa_printf(MSG_ERROR,
90                                    "%s: send on AF_ALG socket failed: %s",
91                                    __func__, strerror(errno));
92                         goto fail;
93                 }
94                 if ((size_t) res < len[i]) {
95                         wpa_printf(MSG_ERROR,
96                                    "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
97                                    __func__, (int) res, (int) len[i]);
98                         goto fail;
99                 }
100         }
101
102         res = recv(t, mac, mac_len, 0);
103         if (res < 0) {
104                 wpa_printf(MSG_ERROR,
105                            "%s: recv on AF_ALG socket failed: %s",
106                            __func__, strerror(errno));
107                 goto fail;
108         }
109         if ((size_t) res < mac_len) {
110                 wpa_printf(MSG_ERROR,
111                            "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
112                            __func__, (int) res, (int) mac_len);
113                 goto fail;
114         }
115
116         ret = 0;
117 fail:
118         close(t);
119         close(s);
120
121         return ret;
122 }
123
124
125 int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
126 {
127         return linux_af_alg_hash_vector("md4", NULL, 0, num_elem, addr, len,
128                                         mac, 16);
129 }
130
131
132 int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
133 {
134         return linux_af_alg_hash_vector("md5", NULL, 0, num_elem, addr, len,
135                                         mac, MD5_MAC_LEN);
136 }
137
138
139 int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
140                 u8 *mac)
141 {
142         return linux_af_alg_hash_vector("sha1", NULL, 0, num_elem, addr, len,
143                                         mac, SHA1_MAC_LEN);
144 }
145
146
147 int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
148                   u8 *mac)
149 {
150         return linux_af_alg_hash_vector("sha256", NULL, 0, num_elem, addr, len,
151                                         mac, SHA256_MAC_LEN);
152 }
153
154
155 int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
156                   u8 *mac)
157 {
158         return linux_af_alg_hash_vector("sha384", NULL, 0, num_elem, addr, len,
159                                         mac, SHA384_MAC_LEN);
160 }
161
162
163 int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
164                   u8 *mac)
165 {
166         return linux_af_alg_hash_vector("sha512", NULL, 0, num_elem, addr, len,
167                                         mac, 64);
168 }
169
170
171 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
172                     const u8 *addr[], const size_t *len, u8 *mac)
173 {
174         return linux_af_alg_hash_vector("hmac(md5)", key, key_len, num_elem,
175                                         addr, len, mac, 16);
176 }
177
178
179 int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
180              u8 *mac)
181 {
182         return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
183 }
184
185
186 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
187                      const u8 *addr[], const size_t *len, u8 *mac)
188 {
189         return linux_af_alg_hash_vector("hmac(sha1)", key, key_len, num_elem,
190                                         addr, len, mac, SHA1_MAC_LEN);
191 }
192
193
194 int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
195               u8 *mac)
196 {
197         return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
198 }
199
200
201 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
202                        const u8 *addr[], const size_t *len, u8 *mac)
203 {
204         return linux_af_alg_hash_vector("hmac(sha256)", key, key_len, num_elem,
205                                         addr, len, mac, SHA256_MAC_LEN);
206 }
207
208
209 int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
210                 size_t data_len, u8 *mac)
211 {
212         return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
213 }
214
215
216 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
217                        const u8 *addr[], const size_t *len, u8 *mac)
218 {
219         return linux_af_alg_hash_vector("hmac(sha384)", key, key_len, num_elem,
220                                         addr, len, mac, SHA384_MAC_LEN);
221 }
222
223
224 int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
225                 size_t data_len, u8 *mac)
226 {
227         return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
228 }
229
230
231 struct crypto_hash {
232         int s;
233         int t;
234         size_t mac_len;
235         int failed;
236 };
237
238
239 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
240                                       size_t key_len)
241 {
242         struct crypto_hash *ctx;
243         const char *name;
244
245         ctx = os_zalloc(sizeof(*ctx));
246         if (!ctx)
247                 return NULL;
248
249         switch (alg) {
250         case CRYPTO_HASH_ALG_MD5:
251                 name = "md5";
252                 ctx->mac_len = MD5_MAC_LEN;
253                 break;
254         case CRYPTO_HASH_ALG_SHA1:
255                 name = "sha1";
256                 ctx->mac_len = SHA1_MAC_LEN;
257                 break;
258         case CRYPTO_HASH_ALG_HMAC_MD5:
259                 name = "hmac(md5)";
260                 ctx->mac_len = MD5_MAC_LEN;
261                 break;
262         case CRYPTO_HASH_ALG_HMAC_SHA1:
263                 name = "hmac(sha1)";
264                 ctx->mac_len = SHA1_MAC_LEN;
265                 break;
266         case CRYPTO_HASH_ALG_SHA256:
267                 name = "sha256";
268                 ctx->mac_len = SHA256_MAC_LEN;
269                 break;
270         case CRYPTO_HASH_ALG_HMAC_SHA256:
271                 name = "hmac(sha256)";
272                 ctx->mac_len = SHA256_MAC_LEN;
273                 break;
274         case CRYPTO_HASH_ALG_SHA384:
275                 name = "sha384";
276                 ctx->mac_len = SHA384_MAC_LEN;
277                 break;
278         case CRYPTO_HASH_ALG_SHA512:
279                 name = "sha512";
280                 ctx->mac_len = 64;
281                 break;
282         default:
283                 os_free(ctx);
284                 return NULL;
285         }
286
287         ctx->s = linux_af_alg_socket("hash", name);
288         if (ctx->s < 0) {
289                 os_free(ctx);
290                 return NULL;
291         }
292
293         if (key && key_len &&
294             setsockopt(ctx->s, SOL_ALG, ALG_SET_KEY, key, key_len) < 0) {
295                 wpa_printf(MSG_ERROR, "%s: setsockopt(ALG_SET_KEY) failed: %s",
296                            __func__, strerror(errno));
297                 close(ctx->s);
298                 os_free(ctx);
299                 return NULL;
300         }
301
302         ctx->t = accept(ctx->s, NULL, NULL);
303         if (ctx->t < 0) {
304                 wpa_printf(MSG_ERROR, "%s: accept on AF_ALG socket failed: %s",
305                            __func__, strerror(errno));
306                 close(ctx->s);
307                 os_free(ctx);
308                 return NULL;
309         }
310
311         return ctx;
312 }
313
314
315 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
316 {
317         ssize_t res;
318
319         if (!ctx)
320                 return;
321
322         res = send(ctx->t, data, len, MSG_MORE);
323         if (res < 0) {
324                 wpa_printf(MSG_ERROR,
325                            "%s: send on AF_ALG socket failed: %s",
326                            __func__, strerror(errno));
327                 ctx->failed = 1;
328                 return;
329         }
330         if ((size_t) res < len) {
331                 wpa_printf(MSG_ERROR,
332                            "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
333                            __func__, (int) res, (int) len);
334                 ctx->failed = 1;
335                 return;
336         }
337 }
338
339
340 static void crypto_hash_deinit(struct crypto_hash *ctx)
341 {
342         close(ctx->s);
343         close(ctx->t);
344         os_free(ctx);
345 }
346
347
348 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
349 {
350         ssize_t res;
351
352         if (!ctx)
353                 return -2;
354
355         if (!mac || !len) {
356                 crypto_hash_deinit(ctx);
357                 return 0;
358         }
359
360         if (ctx->failed) {
361                 crypto_hash_deinit(ctx);
362                 return -2;
363         }
364
365         if (*len < ctx->mac_len) {
366                 crypto_hash_deinit(ctx);
367                 *len = ctx->mac_len;
368                 return -1;
369         }
370         *len = ctx->mac_len;
371
372         res = recv(ctx->t, mac, ctx->mac_len, 0);
373         if (res < 0) {
374                 wpa_printf(MSG_ERROR,
375                            "%s: recv on AF_ALG socket failed: %s",
376                            __func__, strerror(errno));
377                 crypto_hash_deinit(ctx);
378                 return -2;
379         }
380         if ((size_t) res < ctx->mac_len) {
381                 wpa_printf(MSG_ERROR,
382                            "%s: recv on AF_ALG socket did not return full buffer (%d/%d)",
383                            __func__, (int) res, (int) ctx->mac_len);
384                 crypto_hash_deinit(ctx);
385                 return -2;
386         }
387
388         crypto_hash_deinit(ctx);
389
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 }