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