1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2018 Richard Palethorpe <rpalethorpe@suse.com> 4 * Nicolai Stange <nstange@suse.de> 5 */ 6 7 #include <errno.h> 8 #include <stdio.h> 9 10 #define TST_NO_DEFAULT_MAIN 11 #include "tst_test.h" 12 #include "tst_crypto.h" 13 #include "tst_netlink.h" 14 tst_crypto_open(struct tst_crypto_session * ses)15 void tst_crypto_open(struct tst_crypto_session *ses) 16 { 17 const long ret = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO); 18 19 if (ret < 0 && errno == EPROTONOSUPPORT) 20 tst_brk(TCONF | TERRNO, "NETLINK_CRYPTO is probably disabled"); 21 22 if (ret < 0) { 23 tst_brk(TBROK | TERRNO, 24 "socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CRYPTO)"); 25 } 26 27 ses->fd = ret; 28 ses->seq_num = 0; 29 } 30 tst_crypto_close(struct tst_crypto_session * ses)31 void tst_crypto_close(struct tst_crypto_session *ses) 32 { 33 SAFE_CLOSE(ses->fd); 34 } 35 tst_crypto_recv_ack(struct tst_crypto_session * ses)36 static int tst_crypto_recv_ack(struct tst_crypto_session *ses) 37 { 38 uint32_t len; 39 char buf[BUFSIZ]; 40 struct nlmsghdr *nh; 41 42 len = SAFE_NETLINK_RECV(ses->fd, buf, sizeof(buf)); 43 44 for (nh = (struct nlmsghdr *) buf; 45 NLMSG_OK(nh, len); 46 nh = NLMSG_NEXT(nh, len)) { 47 if (nh->nlmsg_seq != ses->seq_num) { 48 tst_brk(TBROK, 49 "Message out of sequence; type=0%hx, seq_num=%u (not %u)", 50 nh->nlmsg_type, nh->nlmsg_seq, ses->seq_num); 51 } 52 53 /* Acks use the error message type with error number set to 54 * zero. Ofcourse we could also receive an actual error. 55 */ 56 if (nh->nlmsg_type == NLMSG_ERROR) 57 return ((struct nlmsgerr *)NLMSG_DATA(nh))->error; 58 59 tst_brk(TBROK, "Unexpected message type; type=0x%hx, seq_num=%u", 60 nh->nlmsg_type, nh->nlmsg_seq); 61 } 62 63 tst_brk(TBROK, "Empty message from netlink socket?"); 64 65 return ENODATA; 66 } 67 tst_crypto_add_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)68 int tst_crypto_add_alg(struct tst_crypto_session *ses, 69 const struct crypto_user_alg *alg) 70 { 71 struct nlmsghdr nh = { 72 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg), 73 .nlmsg_type = CRYPTO_MSG_NEWALG, 74 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, 75 .nlmsg_seq = ++(ses->seq_num), 76 .nlmsg_pid = 0, 77 }; 78 79 SAFE_NETLINK_SEND(ses->fd, &nh, alg); 80 81 return tst_crypto_recv_ack(ses); 82 } 83 tst_crypto_del_alg(struct tst_crypto_session * ses,const struct crypto_user_alg * alg)84 int tst_crypto_del_alg(struct tst_crypto_session *ses, 85 const struct crypto_user_alg *alg) 86 { 87 long ret; 88 unsigned int i = 0; 89 struct nlmsghdr nh = { 90 .nlmsg_len = sizeof(struct nlmsghdr) + sizeof(*alg), 91 .nlmsg_type = CRYPTO_MSG_DELALG, 92 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, 93 .nlmsg_pid = 0, 94 }; 95 96 while (1) { 97 nh.nlmsg_seq = ++(ses->seq_num), 98 99 SAFE_NETLINK_SEND(ses->fd, &nh, alg); 100 101 ret = tst_crypto_recv_ack(ses); 102 if (ret != -EBUSY || i >= ses->retries) 103 break; 104 105 if (usleep(1) && errno != EINTR) 106 tst_brk(TBROK | TERRNO, "usleep(1)"); 107 108 ++i; 109 } 110 111 return ret; 112 } 113