2 * Crypto wrapper for Linux kernel AF_ALG
3 * Copyright (c) 2017, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #include <linux/if_alg.h>
26 static int linux_af_alg_socket(const char *type
, const char *name
)
28 struct sockaddr_alg sa
;
34 s
= socket(AF_ALG
, SOCK_SEQPACKET
, 0);
36 wpa_printf(MSG_ERROR
, "%s: Failed to open AF_ALG socket: %s",
37 __func__
, strerror(errno
));
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) {
47 "%s: Failed to bind AF_ALG socket(%s,%s): %s",
48 __func__
, type
, name
, strerror(errno
));
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
)
67 s
= linux_af_alg_socket("hash", alg
);
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
));
78 t
= accept(s
, NULL
, NULL
);
80 wpa_printf(MSG_ERROR
, "%s: accept on AF_ALG socket failed: %s",
81 __func__
, strerror(errno
));
86 for (i
= 0; i
< num_elem
; i
++) {
87 res
= send(t
, addr
[i
], len
[i
], i
+ 1 < num_elem
? MSG_MORE
: 0);
90 "%s: send on AF_ALG socket failed: %s",
91 __func__
, strerror(errno
));
94 if ((size_t) res
< len
[i
]) {
96 "%s: send on AF_ALG socket did not accept full buffer (%d/%d)",
97 __func__
, (int) res
, (int) len
[i
]);
102 res
= recv(t
, mac
, mac_len
, 0);
104 wpa_printf(MSG_ERROR
,
105 "%s: recv on AF_ALG socket failed: %s",
106 __func__
, strerror(errno
));
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
);
125 int md4_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
, u8
*mac
)
127 return linux_af_alg_hash_vector("md4", NULL
, 0, num_elem
, addr
, len
,
132 int md5_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
, u8
*mac
)
134 return linux_af_alg_hash_vector("md5", NULL
, 0, num_elem
, addr
, len
,
139 int sha1_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
,
142 return linux_af_alg_hash_vector("sha1", NULL
, 0, num_elem
, addr
, len
,
147 int sha256_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
,
150 return linux_af_alg_hash_vector("sha256", NULL
, 0, num_elem
, addr
, len
,
151 mac
, SHA256_MAC_LEN
);
155 int sha384_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
,
158 return linux_af_alg_hash_vector("sha384", NULL
, 0, num_elem
, addr
, len
,
159 mac
, SHA384_MAC_LEN
);
163 int sha512_vector(size_t num_elem
, const u8
*addr
[], const size_t *len
,
166 return linux_af_alg_hash_vector("sha512", NULL
, 0, num_elem
, addr
, len
,
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
)
174 return linux_af_alg_hash_vector("hmac(md5)", key
, key_len
, num_elem
,
179 int hmac_md5(const u8
*key
, size_t key_len
, const u8
*data
, size_t data_len
,
182 return hmac_md5_vector(key
, key_len
, 1, &data
, &data_len
, 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
)
189 return linux_af_alg_hash_vector("hmac(sha1)", key
, key_len
, num_elem
,
190 addr
, len
, mac
, SHA1_MAC_LEN
);
194 int hmac_sha1(const u8
*key
, size_t key_len
, const u8
*data
, size_t data_len
,
197 return hmac_sha1_vector(key
, key_len
, 1, &data
, &data_len
, 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
)
204 return linux_af_alg_hash_vector("hmac(sha256)", key
, key_len
, num_elem
,
205 addr
, len
, mac
, SHA256_MAC_LEN
);
209 int hmac_sha256(const u8
*key
, size_t key_len
, const u8
*data
,
210 size_t data_len
, u8
*mac
)
212 return hmac_sha256_vector(key
, key_len
, 1, &data
, &data_len
, 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
)
219 return linux_af_alg_hash_vector("hmac(sha384)", key
, key_len
, num_elem
,
220 addr
, len
, mac
, SHA384_MAC_LEN
);
224 int hmac_sha384(const u8
*key
, size_t key_len
, const u8
*data
,
225 size_t data_len
, u8
*mac
)
227 return hmac_sha384_vector(key
, key_len
, 1, &data
, &data_len
, mac
);
239 struct crypto_hash
* crypto_hash_init(enum crypto_hash_alg alg
, const u8
*key
,
242 struct crypto_hash
*ctx
;
245 ctx
= os_zalloc(sizeof(*ctx
));
250 case CRYPTO_HASH_ALG_MD5
:
252 ctx
->mac_len
= MD5_MAC_LEN
;
254 case CRYPTO_HASH_ALG_SHA1
:
256 ctx
->mac_len
= SHA1_MAC_LEN
;
258 case CRYPTO_HASH_ALG_HMAC_MD5
:
260 ctx
->mac_len
= MD5_MAC_LEN
;
262 case CRYPTO_HASH_ALG_HMAC_SHA1
:
264 ctx
->mac_len
= SHA1_MAC_LEN
;
266 case CRYPTO_HASH_ALG_SHA256
:
268 ctx
->mac_len
= SHA256_MAC_LEN
;
270 case CRYPTO_HASH_ALG_HMAC_SHA256
:
271 name
= "hmac(sha256)";
272 ctx
->mac_len
= SHA256_MAC_LEN
;
274 case CRYPTO_HASH_ALG_SHA384
:
276 ctx
->mac_len
= SHA384_MAC_LEN
;
278 case CRYPTO_HASH_ALG_SHA512
:
287 ctx
->s
= linux_af_alg_socket("hash", name
);
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
));
302 ctx
->t
= accept(ctx
->s
, NULL
, NULL
);
304 wpa_printf(MSG_ERROR
, "%s: accept on AF_ALG socket failed: %s",
305 __func__
, strerror(errno
));
315 void crypto_hash_update(struct crypto_hash
*ctx
, const u8
*data
, size_t len
)
322 res
= send(ctx
->t
, data
, len
, MSG_MORE
);
324 wpa_printf(MSG_ERROR
,
325 "%s: send on AF_ALG socket failed: %s",
326 __func__
, strerror(errno
));
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
);
340 static void crypto_hash_deinit(struct crypto_hash
*ctx
)
348 int crypto_hash_finish(struct crypto_hash
*ctx
, u8
*mac
, size_t *len
)
356 crypto_hash_deinit(ctx
);
361 crypto_hash_deinit(ctx
);
365 if (*len
< ctx
->mac_len
) {
366 crypto_hash_deinit(ctx
);
372 res
= recv(ctx
->t
, mac
, ctx
->mac_len
, 0);
374 wpa_printf(MSG_ERROR
,
375 "%s: recv on AF_ALG socket failed: %s",
376 __func__
, strerror(errno
));
377 crypto_hash_deinit(ctx
);
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
);
388 crypto_hash_deinit(ctx
);
393 struct linux_af_alg_skcipher
{
399 static void linux_af_alg_skcipher_deinit(struct linux_af_alg_skcipher
*skcipher
)
403 if (skcipher
->s
>= 0)
405 if (skcipher
->t
>= 0)
411 static struct linux_af_alg_skcipher
*
412 linux_af_alg_skcipher(const char *alg
, const u8
*key
, size_t key_len
)
414 struct linux_af_alg_skcipher
*skcipher
;
416 skcipher
= os_zalloc(sizeof(*skcipher
));
421 skcipher
->s
= linux_af_alg_socket("skcipher", alg
);
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
));
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
));
440 linux_af_alg_skcipher_deinit(skcipher
);
445 static int linux_af_alg_skcipher_oper(struct linux_af_alg_skcipher
*skcipher
,
446 int enc
, const u8
*in
, u8
*out
)
448 char buf
[CMSG_SPACE(sizeof(u32
))];
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
));
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
;
470 ret
= sendmsg(skcipher
->t
, &msg
, 0);
472 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
473 __func__
, strerror(errno
));
477 ret
= read(skcipher
->t
, out
, AES_BLOCK_SIZE
);
479 wpa_printf(MSG_ERROR
, "%s: read failed: %s",
480 __func__
, strerror(errno
));
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
);
494 void * aes_encrypt_init(const u8
*key
, size_t len
)
496 return linux_af_alg_skcipher("ecb(aes)", key
, len
);
500 int aes_encrypt(void *ctx
, const u8
*plain
, u8
*crypt
)
502 struct linux_af_alg_skcipher
*skcipher
= ctx
;
504 return linux_af_alg_skcipher_oper(skcipher
, 1, plain
, crypt
);
508 void aes_encrypt_deinit(void *ctx
)
510 linux_af_alg_skcipher_deinit(ctx
);
514 void * aes_decrypt_init(const u8
*key
, size_t len
)
516 return linux_af_alg_skcipher("ecb(aes)", key
, len
);
520 int aes_decrypt(void *ctx
, const u8
*crypt
, u8
*plain
)
522 struct linux_af_alg_skcipher
*skcipher
= ctx
;
524 return linux_af_alg_skcipher_oper(skcipher
, 0, crypt
, plain
);
528 void aes_decrypt_deinit(void *ctx
)
530 linux_af_alg_skcipher_deinit(ctx
);
534 int rc4_skip(const u8
*key
, size_t keylen
, size_t skip
,
535 u8
*data
, size_t data_len
)
537 struct linux_af_alg_skcipher
*skcipher
;
539 char buf
[CMSG_SPACE(sizeof(u32
))];
546 skip_buf
= os_zalloc(skip
+ 1);
549 skcipher
= linux_af_alg_skcipher("ecb(arc4)", key
, keylen
);
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
));
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
;
572 ret
= sendmsg(skcipher
->t
, &msg
, 0);
574 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
575 __func__
, strerror(errno
));
577 linux_af_alg_skcipher_deinit(skcipher
);
582 msg
.msg_control
= NULL
;
583 msg
.msg_controllen
= 0;
584 ret
= recvmsg(skcipher
->t
, &msg
, 0);
586 wpa_printf(MSG_ERROR
, "%s: recvmsg failed: %s",
587 __func__
, strerror(errno
));
588 linux_af_alg_skcipher_deinit(skcipher
);
591 linux_af_alg_skcipher_deinit(skcipher
);
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
));
604 int des_encrypt(const u8
*clear
, const u8
*key
, u8
*cypher
)
606 u8 pkey
[8], next
, tmp
;
608 struct linux_af_alg_skcipher
*skcipher
;
609 char buf
[CMSG_SPACE(sizeof(u32
))];
617 /* Add parity bits to the key */
619 for (i
= 0; i
< 7; i
++) {
621 pkey
[i
] = (tmp
>> i
) | next
| 1;
622 next
= tmp
<< (7 - i
);
626 skcipher
= linux_af_alg_skcipher("ecb(des)", pkey
, sizeof(pkey
));
630 io
[0].iov_base
= (void *) clear
;
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
));
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
;
645 ret
= sendmsg(skcipher
->t
, &msg
, 0);
647 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
648 __func__
, strerror(errno
));
652 ret
= read(skcipher
->t
, cypher
, 8);
654 wpa_printf(MSG_ERROR
, "%s: read failed: %s",
655 __func__
, strerror(errno
));
659 wpa_printf(MSG_ERROR
,
660 "%s: read did not return full data (%d/8)",
661 __func__
, (int) ret
);
667 linux_af_alg_skcipher_deinit(skcipher
);
672 static int aes_128_cbc_oper(const u8
*key
, int enc
, const u8
*iv
,
673 u8
*data
, size_t data_len
)
675 struct linux_af_alg_skcipher
*skcipher
;
682 struct af_alg_iv
*alg_iv
;
683 size_t iv_len
= AES_BLOCK_SIZE
;
685 skcipher
= linux_af_alg_skcipher("cbc(aes)", key
, 16);
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
);
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
;
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
);
714 ret
= sendmsg(skcipher
->t
, &msg
, 0);
716 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
717 __func__
, strerror(errno
));
718 linux_af_alg_skcipher_deinit(skcipher
);
722 ret
= recvmsg(skcipher
->t
, &msg
, 0);
724 wpa_printf(MSG_ERROR
, "%s: recvmsg failed: %s",
725 __func__
, strerror(errno
));
726 linux_af_alg_skcipher_deinit(skcipher
);
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
);
737 linux_af_alg_skcipher_deinit(skcipher
);
742 int aes_128_cbc_encrypt(const u8
*key
, const u8
*iv
, u8
*data
, size_t data_len
)
744 return aes_128_cbc_oper(key
, 1, iv
, data
, data_len
);
748 int aes_128_cbc_decrypt(const u8
*key
, const u8
*iv
, u8
*data
, size_t data_len
)
750 return aes_128_cbc_oper(key
, 0, iv
, data
, data_len
);
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
)
757 return linux_af_alg_hash_vector("cmac(aes)", key
, key_len
, num_elem
,
758 addr
, len
, mac
, AES_BLOCK_SIZE
);
762 int omac1_aes_128_vector(const u8
*key
, size_t num_elem
,
763 const u8
*addr
[], const size_t *len
, u8
*mac
)
765 return omac1_aes_vector(key
, 16, num_elem
, addr
, len
, mac
);
769 int omac1_aes_128(const u8
*key
, const u8
*data
, size_t data_len
, u8
*mac
)
771 return omac1_aes_128_vector(key
, 1, &data
, &data_len
, mac
);
775 int omac1_aes_256(const u8
*key
, const u8
*data
, size_t data_len
, u8
*mac
)
777 return omac1_aes_vector(key
, 32, 1, &data
, &data_len
, mac
);
781 int aes_unwrap(const u8
*kek
, size_t kek_len
, int n
, const u8
*cipher
,
784 struct linux_af_alg_skcipher
*skcipher
;
791 struct af_alg_iv
*alg_iv
;
794 skcipher
= linux_af_alg_skcipher("kw(aes)", kek
, kek_len
);
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
);
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
;
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
);
823 ret
= sendmsg(skcipher
->t
, &msg
, 0);
825 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
826 __func__
, strerror(errno
));
830 ret
= read(skcipher
->t
, plain
, n
* 8);
832 wpa_printf(MSG_ERROR
, "%s: read failed: %s",
833 __func__
, strerror(errno
));
834 linux_af_alg_skcipher_deinit(skcipher
);
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
);
845 linux_af_alg_skcipher_deinit(skcipher
);
850 struct crypto_cipher
{
851 struct linux_af_alg_skcipher
*skcipher
;
855 struct crypto_cipher
* crypto_cipher_init(enum crypto_cipher_alg alg
,
856 const u8
*iv
, const u8
*key
,
859 struct crypto_cipher
*ctx
;
861 struct af_alg_iv
*alg_iv
;
868 ctx
= os_zalloc(sizeof(*ctx
));
873 case CRYPTO_CIPHER_ALG_RC4
:
876 case CRYPTO_CIPHER_ALG_AES
:
878 iv_len
= AES_BLOCK_SIZE
;
880 case CRYPTO_CIPHER_ALG_3DES
:
881 name
= "cbc(des3_ede)";
884 case CRYPTO_CIPHER_ALG_DES
:
893 ctx
->skcipher
= linux_af_alg_skcipher(name
, key
, key_len
);
894 if (!ctx
->skcipher
) {
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
);
912 ret
= sendmsg(ctx
->skcipher
->t
, &msg
, 0);
914 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
915 __func__
, strerror(errno
));
916 linux_af_alg_skcipher_deinit(ctx
->skcipher
);
926 static int crypto_cipher_oper(struct crypto_cipher
*ctx
, u32 type
, const u8
*in
,
929 char buf
[CMSG_SPACE(sizeof(u32
))];
936 io
[0].iov_base
= (void *) in
;
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
));
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
);
951 ret
= sendmsg(ctx
->skcipher
->t
, &msg
, 0);
953 wpa_printf(MSG_ERROR
, "%s: sendmsg failed: %s",
954 __func__
, strerror(errno
));
958 ret
= read(ctx
->skcipher
->t
, out
, len
);
960 wpa_printf(MSG_ERROR
, "%s: read failed: %s",
961 __func__
, strerror(errno
));
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
);
975 int crypto_cipher_encrypt(struct crypto_cipher
*ctx
, const u8
*plain
,
976 u8
*crypt
, size_t len
)
978 return crypto_cipher_oper(ctx
, ALG_OP_ENCRYPT
, plain
, crypt
, len
);
982 int crypto_cipher_decrypt(struct crypto_cipher
*ctx
, const u8
*crypt
,
983 u8
*plain
, size_t len
)
985 return crypto_cipher_oper(ctx
, ALG_OP_DECRYPT
, crypt
, plain
, len
);
989 void crypto_cipher_deinit(struct crypto_cipher
*ctx
)
992 linux_af_alg_skcipher_deinit(ctx
->skcipher
);
998 int crypto_global_init(void)
1004 void crypto_global_deinit(void)