]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - src/crypto/crypto_linux.c
Import wpa_supplicant/hostapd 2.7
[FreeBSD/FreeBSD.git] / 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         return 0;
390 }
391
392
393 struct linux_af_alg_skcipher {
394         int s;
395         int t;
396 };
397
398
399 static 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
411 static struct linux_af_alg_skcipher *
412 linux_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;
439 fail:
440         linux_af_alg_skcipher_deinit(skcipher);
441         return NULL;
442 }
443
444
445 static 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
494 void * aes_encrypt_init(const u8 *key, size_t len)
495 {
496         return linux_af_alg_skcipher("ecb(aes)", key, len);
497 }
498
499
500 int 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
508 void aes_encrypt_deinit(void *ctx)
509 {
510         linux_af_alg_skcipher_deinit(ctx);
511 }
512
513
514 void * aes_decrypt_init(const u8 *key, size_t len)
515 {
516         return linux_af_alg_skcipher("ecb(aes)", key, len);
517 }
518
519
520 int 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
528 void aes_decrypt_deinit(void *ctx)
529 {
530         linux_af_alg_skcipher_deinit(ctx);
531 }
532
533
534 int 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
604 int 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;
666 fail:
667         linux_af_alg_skcipher_deinit(skcipher);
668         return res;
669 }
670
671
672 static 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
742 int 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
748 int 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
754 int 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
762 int 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
769 int 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
775 int 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
781 int 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
850 struct crypto_cipher {
851         struct linux_af_alg_skcipher *skcipher;
852 };
853
854
855 struct 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
926 static 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
975 int 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
982 int 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
989 void 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
998 int crypto_global_init(void)
999 {
1000         return 0;
1001 }
1002
1003
1004 void crypto_global_deinit(void)
1005 {
1006 }