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
linux_af_alg_socket(const char * type,const char * name)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
linux_af_alg_hash_vector(const char * alg,const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac,size_t mac_len)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
md4_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
md5_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
sha1_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
sha256_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
sha384_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
sha512_vector(size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
hmac_md5_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
hmac_md5(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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
hmac_sha1_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
hmac_sha1(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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
hmac_sha256_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
hmac_sha256(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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
hmac_sha384_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)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
hmac_sha384(const u8 * key,size_t key_len,const u8 * data,size_t data_len,u8 * mac)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
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)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
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)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
crypto_hash_deinit(struct crypto_hash * ctx)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
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)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 *len = ctx->mac_len;
367 crypto_hash_deinit(ctx);
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
linux_af_alg_skcipher_deinit(struct linux_af_alg_skcipher * skcipher)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 *
linux_af_alg_skcipher(const char * alg,const u8 * key,size_t key_len)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
linux_af_alg_skcipher_oper(struct linux_af_alg_skcipher * skcipher,int enc,const u8 * in,u8 * out)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
aes_encrypt_init(const u8 * key,size_t len)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
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)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
aes_encrypt_deinit(void * ctx)511 void aes_encrypt_deinit(void *ctx)
512 {
513 linux_af_alg_skcipher_deinit(ctx);
514 }
515
516
aes_decrypt_init(const u8 * key,size_t len)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
aes_decrypt(void * ctx,const u8 * crypt,u8 * plain)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
aes_decrypt_deinit(void * ctx)531 void aes_decrypt_deinit(void *ctx)
532 {
533 linux_af_alg_skcipher_deinit(ctx);
534 }
535
536
rc4_skip(const u8 * key,size_t keylen,size_t skip,u8 * data,size_t data_len)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
584 msg.msg_control = NULL;
585 msg.msg_controllen = 0;
586 ret = recvmsg(skcipher->t, &msg, 0);
587 if (ret < 0) {
588 wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
589 __func__, strerror(errno));
590 os_free(skip_buf);
591 linux_af_alg_skcipher_deinit(skcipher);
592 return -1;
593 }
594 os_free(skip_buf);
595 linux_af_alg_skcipher_deinit(skcipher);
596
597 if ((size_t) ret < skip + data_len) {
598 wpa_printf(MSG_ERROR,
599 "%s: recvmsg did not return full data (%d/%d)",
600 __func__, (int) ret, (int) (skip + data_len));
601 return -1;
602 }
603
604 return 0;
605 }
606
607
des_encrypt(const u8 * clear,const u8 * key,u8 * cypher)608 int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
609 {
610 u8 pkey[8], next, tmp;
611 int i;
612 struct linux_af_alg_skcipher *skcipher;
613 char buf[CMSG_SPACE(sizeof(u32))];
614 struct iovec io[1];
615 struct msghdr msg;
616 struct cmsghdr *hdr;
617 ssize_t ret;
618 u32 *op;
619 int res = -1;
620
621 /* Add parity bits to the key */
622 next = 0;
623 for (i = 0; i < 7; i++) {
624 tmp = key[i];
625 pkey[i] = (tmp >> i) | next | 1;
626 next = tmp << (7 - i);
627 }
628 pkey[i] = next | 1;
629
630 skcipher = linux_af_alg_skcipher("ecb(des)", pkey, sizeof(pkey));
631 if (!skcipher)
632 goto fail;
633
634 io[0].iov_base = (void *) clear;
635 io[0].iov_len = 8;
636 os_memset(&msg, 0, sizeof(msg));
637 os_memset(buf, 0, sizeof(buf));
638 msg.msg_control = buf;
639 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
640 msg.msg_iov = io;
641 msg.msg_iovlen = 1;
642 hdr = CMSG_FIRSTHDR(&msg);
643 hdr->cmsg_level = SOL_ALG;
644 hdr->cmsg_type = ALG_SET_OP;
645 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
646 op = (u32 *) CMSG_DATA(hdr);
647 *op = ALG_OP_ENCRYPT;
648
649 ret = sendmsg(skcipher->t, &msg, 0);
650 if (ret < 0) {
651 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
652 __func__, strerror(errno));
653 goto fail;
654 }
655
656 ret = read(skcipher->t, cypher, 8);
657 if (ret < 0) {
658 wpa_printf(MSG_ERROR, "%s: read failed: %s",
659 __func__, strerror(errno));
660 goto fail;
661 }
662 if (ret < 8) {
663 wpa_printf(MSG_ERROR,
664 "%s: read did not return full data (%d/8)",
665 __func__, (int) ret);
666 goto fail;
667 }
668
669 res = 0;
670 fail:
671 linux_af_alg_skcipher_deinit(skcipher);
672 return res;
673 }
674
675
aes_128_cbc_oper(const u8 * key,int enc,const u8 * iv,u8 * data,size_t data_len)676 static int aes_128_cbc_oper(const u8 *key, int enc, const u8 *iv,
677 u8 *data, size_t data_len)
678 {
679 struct linux_af_alg_skcipher *skcipher;
680 char buf[100];
681 struct iovec io[1];
682 struct msghdr msg;
683 struct cmsghdr *hdr;
684 ssize_t ret;
685 u32 *op;
686 struct af_alg_iv *alg_iv;
687 size_t iv_len = AES_BLOCK_SIZE;
688
689 skcipher = linux_af_alg_skcipher("cbc(aes)", key, 16);
690 if (!skcipher)
691 return -1;
692
693 io[0].iov_base = (void *) data;
694 io[0].iov_len = data_len;
695 os_memset(&msg, 0, sizeof(msg));
696 os_memset(buf, 0, sizeof(buf));
697 msg.msg_control = buf;
698 msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
699 CMSG_SPACE(sizeof(*alg_iv) + iv_len);
700 msg.msg_iov = io;
701 msg.msg_iovlen = 1;
702
703 hdr = CMSG_FIRSTHDR(&msg);
704 hdr->cmsg_level = SOL_ALG;
705 hdr->cmsg_type = ALG_SET_OP;
706 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
707 op = (u32 *) CMSG_DATA(hdr);
708 *op = enc ? ALG_OP_ENCRYPT : ALG_OP_DECRYPT;
709
710 hdr = CMSG_NXTHDR(&msg, hdr);
711 hdr->cmsg_level = SOL_ALG;
712 hdr->cmsg_type = ALG_SET_IV;
713 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
714 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
715 alg_iv->ivlen = iv_len;
716 os_memcpy(alg_iv->iv, iv, iv_len);
717
718 ret = sendmsg(skcipher->t, &msg, 0);
719 if (ret < 0) {
720 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
721 __func__, strerror(errno));
722 linux_af_alg_skcipher_deinit(skcipher);
723 return -1;
724 }
725
726 ret = recvmsg(skcipher->t, &msg, 0);
727 if (ret < 0) {
728 wpa_printf(MSG_ERROR, "%s: recvmsg failed: %s",
729 __func__, strerror(errno));
730 linux_af_alg_skcipher_deinit(skcipher);
731 return -1;
732 }
733 if ((size_t) ret < data_len) {
734 wpa_printf(MSG_ERROR,
735 "%s: recvmsg not return full data (%d/%d)",
736 __func__, (int) ret, (int) data_len);
737 linux_af_alg_skcipher_deinit(skcipher);
738 return -1;
739 }
740
741 linux_af_alg_skcipher_deinit(skcipher);
742 return 0;
743 }
744
745
aes_128_cbc_encrypt(const u8 * key,const u8 * iv,u8 * data,size_t data_len)746 int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
747 {
748 return aes_128_cbc_oper(key, 1, iv, data, data_len);
749 }
750
751
aes_128_cbc_decrypt(const u8 * key,const u8 * iv,u8 * data,size_t data_len)752 int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
753 {
754 return aes_128_cbc_oper(key, 0, iv, data, data_len);
755 }
756
757
omac1_aes_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)758 int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
759 const u8 *addr[], const size_t *len, u8 *mac)
760 {
761 return linux_af_alg_hash_vector("cmac(aes)", key, key_len, num_elem,
762 addr, len, mac, AES_BLOCK_SIZE);
763 }
764
765
omac1_aes_128_vector(const u8 * key,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)766 int omac1_aes_128_vector(const u8 *key, size_t num_elem,
767 const u8 *addr[], const size_t *len, u8 *mac)
768 {
769 return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
770 }
771
772
omac1_aes_128(const u8 * key,const u8 * data,size_t data_len,u8 * mac)773 int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
774 {
775 return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
776 }
777
778
omac1_aes_256(const u8 * key,const u8 * data,size_t data_len,u8 * mac)779 int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
780 {
781 return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
782 }
783
784
aes_unwrap(const u8 * kek,size_t kek_len,int n,const u8 * cipher,u8 * plain)785 int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
786 u8 *plain)
787 {
788 struct linux_af_alg_skcipher *skcipher;
789 char buf[100];
790 struct iovec io[1];
791 struct msghdr msg;
792 struct cmsghdr *hdr;
793 ssize_t ret;
794 u32 *op;
795 struct af_alg_iv *alg_iv;
796 size_t iv_len = 8;
797
798 skcipher = linux_af_alg_skcipher("kw(aes)", kek, kek_len);
799 if (!skcipher)
800 return -1;
801
802 io[0].iov_base = (void *) (cipher + iv_len);
803 io[0].iov_len = n * 8;
804 os_memset(&msg, 0, sizeof(msg));
805 os_memset(buf, 0, sizeof(buf));
806 msg.msg_control = buf;
807 msg.msg_controllen = CMSG_SPACE(sizeof(u32)) +
808 CMSG_SPACE(sizeof(*alg_iv) + iv_len);
809 msg.msg_iov = io;
810 msg.msg_iovlen = 1;
811
812 hdr = CMSG_FIRSTHDR(&msg);
813 hdr->cmsg_level = SOL_ALG;
814 hdr->cmsg_type = ALG_SET_OP;
815 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
816 op = (u32 *) CMSG_DATA(hdr);
817 *op = ALG_OP_DECRYPT;
818
819 hdr = CMSG_NXTHDR(&msg, hdr);
820 hdr->cmsg_level = SOL_ALG;
821 hdr->cmsg_type = ALG_SET_IV;
822 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
823 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
824 alg_iv->ivlen = iv_len;
825 os_memcpy(alg_iv->iv, cipher, iv_len);
826
827 ret = sendmsg(skcipher->t, &msg, 0);
828 if (ret < 0) {
829 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
830 __func__, strerror(errno));
831 return -1;
832 }
833
834 ret = read(skcipher->t, plain, n * 8);
835 if (ret < 0) {
836 wpa_printf(MSG_ERROR, "%s: read failed: %s",
837 __func__, strerror(errno));
838 linux_af_alg_skcipher_deinit(skcipher);
839 return -1;
840 }
841 if (ret < n * 8) {
842 wpa_printf(MSG_ERROR,
843 "%s: read not return full data (%d/%d)",
844 __func__, (int) ret, n * 8);
845 linux_af_alg_skcipher_deinit(skcipher);
846 return -1;
847 }
848
849 linux_af_alg_skcipher_deinit(skcipher);
850 return 0;
851 }
852
853
854 struct crypto_cipher {
855 struct linux_af_alg_skcipher *skcipher;
856 };
857
858
crypto_cipher_init(enum crypto_cipher_alg alg,const u8 * iv,const u8 * key,size_t key_len)859 struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
860 const u8 *iv, const u8 *key,
861 size_t key_len)
862 {
863 struct crypto_cipher *ctx;
864 const char *name;
865 struct af_alg_iv *alg_iv;
866 size_t iv_len = 0;
867 char buf[100];
868 struct msghdr msg;
869 struct cmsghdr *hdr;
870 ssize_t ret;
871
872 ctx = os_zalloc(sizeof(*ctx));
873 if (!ctx)
874 return NULL;
875
876 switch (alg) {
877 case CRYPTO_CIPHER_ALG_RC4:
878 name = "ecb(arc4)";
879 break;
880 case CRYPTO_CIPHER_ALG_AES:
881 name = "cbc(aes)";
882 iv_len = AES_BLOCK_SIZE;
883 break;
884 case CRYPTO_CIPHER_ALG_3DES:
885 name = "cbc(des3_ede)";
886 iv_len = 8;
887 break;
888 case CRYPTO_CIPHER_ALG_DES:
889 name = "cbc(des)";
890 iv_len = 8;
891 break;
892 default:
893 os_free(ctx);
894 return NULL;
895 }
896
897 ctx->skcipher = linux_af_alg_skcipher(name, key, key_len);
898 if (!ctx->skcipher) {
899 os_free(ctx);
900 return NULL;
901 }
902
903 if (iv && iv_len) {
904 os_memset(&msg, 0, sizeof(msg));
905 os_memset(buf, 0, sizeof(buf));
906 msg.msg_control = buf;
907 msg.msg_controllen = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
908 hdr = CMSG_FIRSTHDR(&msg);
909 hdr->cmsg_level = SOL_ALG;
910 hdr->cmsg_type = ALG_SET_IV;
911 hdr->cmsg_len = CMSG_SPACE(sizeof(*alg_iv) + iv_len);
912 alg_iv = (struct af_alg_iv *) CMSG_DATA(hdr);
913 alg_iv->ivlen = iv_len;
914 os_memcpy(alg_iv->iv, iv, iv_len);
915
916 ret = sendmsg(ctx->skcipher->t, &msg, 0);
917 if (ret < 0) {
918 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
919 __func__, strerror(errno));
920 linux_af_alg_skcipher_deinit(ctx->skcipher);
921 os_free(ctx);
922 return NULL;
923 }
924 }
925
926 return ctx;
927 }
928
929
crypto_cipher_oper(struct crypto_cipher * ctx,u32 type,const u8 * in,u8 * out,size_t len)930 static int crypto_cipher_oper(struct crypto_cipher *ctx, u32 type, const u8 *in,
931 u8 *out, size_t len)
932 {
933 char buf[CMSG_SPACE(sizeof(u32))];
934 struct iovec io[1];
935 struct msghdr msg;
936 struct cmsghdr *hdr;
937 ssize_t ret;
938 u32 *op;
939
940 io[0].iov_base = (void *) in;
941 io[0].iov_len = len;
942 os_memset(&msg, 0, sizeof(msg));
943 os_memset(buf, 0, sizeof(buf));
944 msg.msg_control = buf;
945 msg.msg_controllen = CMSG_SPACE(sizeof(u32));
946 msg.msg_iov = io;
947 msg.msg_iovlen = 1;
948 hdr = CMSG_FIRSTHDR(&msg);
949 hdr->cmsg_level = SOL_ALG;
950 hdr->cmsg_type = ALG_SET_OP;
951 hdr->cmsg_len = CMSG_LEN(sizeof(u32));
952 op = (u32 *) CMSG_DATA(hdr);
953 *op = type;
954
955 ret = sendmsg(ctx->skcipher->t, &msg, 0);
956 if (ret < 0) {
957 wpa_printf(MSG_ERROR, "%s: sendmsg failed: %s",
958 __func__, strerror(errno));
959 return -1;
960 }
961
962 ret = read(ctx->skcipher->t, out, len);
963 if (ret < 0) {
964 wpa_printf(MSG_ERROR, "%s: read failed: %s",
965 __func__, strerror(errno));
966 return -1;
967 }
968 if (ret < (ssize_t) len) {
969 wpa_printf(MSG_ERROR,
970 "%s: read did not return full data (%d/%d)",
971 __func__, (int) ret, (int) len);
972 return -1;
973 }
974
975 return 0;
976 }
977
978
crypto_cipher_encrypt(struct crypto_cipher * ctx,const u8 * plain,u8 * crypt,size_t len)979 int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
980 u8 *crypt, size_t len)
981 {
982 return crypto_cipher_oper(ctx, ALG_OP_ENCRYPT, plain, crypt, len);
983 }
984
985
crypto_cipher_decrypt(struct crypto_cipher * ctx,const u8 * crypt,u8 * plain,size_t len)986 int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
987 u8 *plain, size_t len)
988 {
989 return crypto_cipher_oper(ctx, ALG_OP_DECRYPT, crypt, plain, len);
990 }
991
992
crypto_cipher_deinit(struct crypto_cipher * ctx)993 void crypto_cipher_deinit(struct crypto_cipher *ctx)
994 {
995 if (ctx) {
996 linux_af_alg_skcipher_deinit(ctx->skcipher);
997 os_free(ctx);
998 }
999 }
1000
1001
crypto_global_init(void)1002 int crypto_global_init(void)
1003 {
1004 return 0;
1005 }
1006
1007
crypto_global_deinit(void)1008 void crypto_global_deinit(void)
1009 {
1010 }
1011
1012
crypto_unload(void)1013 void crypto_unload(void)
1014 {
1015 }
1016