Message ID | 1537351855-16618-3-git-send-email-clabbe@baylibre.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Herbert Xu |
Headers | show |
Series | crypto: Implement a generic crypto statistics | expand |
On 19 September 2018 at 12:10, Corentin Labbe <clabbe@baylibre.com> wrote: > This patch adds an userspace tool for displaying kernel crypto API > statistics. > > Signed-off-by: Corentin Labbe <clabbe@baylibre.com> How do I actually build this thing? > --- > tools/crypto/getstat.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 294 insertions(+) > create mode 100644 tools/crypto/getstat.c > > diff --git a/tools/crypto/getstat.c b/tools/crypto/getstat.c > new file mode 100644 > index 000000000000..24115173a483 > --- /dev/null > +++ b/tools/crypto/getstat.c > @@ -0,0 +1,294 @@ > +/* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller <smueller@chronox.de> */ > +#include <errno.h> > +#include <linux/cryptouser.h> > +#include <linux/netlink.h> > +#include <linux/rtnetlink.h> > +#include <sys/types.h> > +#include <sys/socket.h> > +#include <stdlib.h> > +#include <stdio.h> > +#include <string.h> > +#include <time.h> > +#include <unistd.h> > + > +#define CR_RTA(x) ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg)))) > + > +static int get_stat(const char *drivername) > +{ > + struct { > + struct nlmsghdr n; > + struct crypto_user_alg cru; > + } req; > + struct sockaddr_nl nl; > + int sd = 0, ret; > + socklen_t addr_len; > + struct iovec iov; > + struct msghdr msg; > + char buf[4096]; > + struct nlmsghdr *res_n = (struct nlmsghdr *)buf; > + struct crypto_user_alg *cru_res = NULL; > + int res_len = 0; > + struct rtattr *tb[CRYPTOCFGA_MAX + 1]; > + struct rtattr *rta; > + struct nlmsgerr *errmsg; > + > + memset(&req, 0, sizeof(req)); > + memset(&buf, 0, sizeof(buf)); > + memset(&msg, 0, sizeof(msg)); > + > + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.cru)); > + req.n.nlmsg_flags = NLM_F_REQUEST; > + req.n.nlmsg_type = CRYPTO_MSG_GETSTAT; > + req.n.nlmsg_seq = time(NULL); > + > + strncpy(req.cru.cru_driver_name, drivername, strlen(drivername)); > + > + sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_CRYPTO); > + if (sd < 0) { > + fprintf(stderr, "Netlink error: cannot open netlink socket"); > + return -errno; > + } > + memset(&nl, 0, sizeof(nl)); > + nl.nl_family = AF_NETLINK; > + if (bind(sd, (struct sockaddr *)&nl, sizeof(nl)) < 0) { > + ret = -errno; > + fprintf(stderr, "Netlink error: cannot bind netlink socket"); > + goto out; > + } > + > + /* sanity check that netlink socket was successfully opened */ > + addr_len = sizeof(nl); > + if (getsockname(sd, (struct sockaddr *)&nl, &addr_len) < 0) { > + ret = -errno; > + printf("Netlink error: cannot getsockname"); > + goto out; > + } > + if (addr_len != sizeof(nl)) { > + ret = -errno; > + printf("Netlink error: wrong address length %d", addr_len); > + goto out; > + } > + if (nl.nl_family != AF_NETLINK) { > + ret = -errno; > + printf("Netlink error: wrong address family %d", > + nl.nl_family); > + goto out; > + } > + > + memset(&nl, 0, sizeof(nl)); > + nl.nl_family = AF_NETLINK; > + iov.iov_base = (void *)&req.n; > + iov.iov_len = req.n.nlmsg_len; > + msg.msg_name = &nl; > + msg.msg_namelen = sizeof(nl); > + msg.msg_iov = &iov; > + msg.msg_iovlen = 1; > + if (sendmsg(sd, &msg, 0) < 0) { > + ret = -errno; > + printf("Netlink error: sendmsg failed"); > + goto out; > + } > + memset(buf, 0, sizeof(buf)); > + iov.iov_base = buf; > + while (1) { > + iov.iov_len = sizeof(buf); > + ret = recvmsg(sd, &msg, 0); > + if (ret < 0) { > + if (errno == EINTR || errno == EAGAIN) > + continue; > + ret = -errno; > + printf("Netlink error: netlink receive error"); > + goto out; > + } > + if (ret == 0) { > + ret = -errno; > + printf("Netlink error: no data"); > + goto out; > + } > + if (ret > sizeof(buf)) { > + ret = -errno; > + printf("Netlink error: received too much data"); > + goto out; > + } > + break; > + } > + > + ret = -EFAULT; > + res_len = res_n->nlmsg_len; > + if (res_n->nlmsg_type == NLMSG_ERROR) { > + errmsg = NLMSG_DATA(res_n); > + fprintf(stderr, "Fail with %d\n", errmsg->error); > + ret = errmsg->error; > + goto out; > + } > + > + if (res_n->nlmsg_type == CRYPTO_MSG_GETSTAT) { > + cru_res = NLMSG_DATA(res_n); > + res_len -= NLMSG_SPACE(sizeof(*cru_res)); > + } > + if (res_len < 0) { > + printf("Netlink error: nlmsg len %d\n", res_len); > + goto out; > + } > + > + if (!cru_res) { > + ret = -EFAULT; > + printf("Netlink error: no cru_res\n"); > + goto out; > + } > + > + rta = CR_RTA(cru_res); > + memset(tb, 0, sizeof(struct rtattr *) * (CRYPTOCFGA_MAX + 1)); > + while (RTA_OK(rta, res_len)) { > + if ((rta->rta_type <= CRYPTOCFGA_MAX) && (!tb[rta->rta_type])) > + tb[rta->rta_type] = rta; > + rta = RTA_NEXT(rta, res_len); > + } > + if (res_len) { > + printf("Netlink error: unprocessed data %d", > + res_len); > + goto out; > + } > + > + if (tb[CRYPTOCFGA_STAT_HASH]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_HASH]; > + struct crypto_stat *rhash = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tHash\n\tHash: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rhash->stat_hash_cnt, rhash->stat_hash_tlen, > + rhash->stat_hash_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_COMPRESS]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_COMPRESS]; > + struct crypto_stat *rblk = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tCompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rblk->stat_compress_cnt, rblk->stat_compress_tlen, > + rblk->stat_decompress_cnt, rblk->stat_decompress_tlen, > + rblk->stat_compress_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_ACOMP]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_ACOMP]; > + struct crypto_stat *rcomp = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tACompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rcomp->stat_compress_cnt, rcomp->stat_compress_tlen, > + rcomp->stat_decompress_cnt, rcomp->stat_decompress_tlen, > + rcomp->stat_compress_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_AEAD]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_AEAD]; > + struct crypto_stat *raead = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tAEAD\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + raead->stat_encrypt_cnt, raead->stat_encrypt_tlen, > + raead->stat_decrypt_cnt, raead->stat_decrypt_tlen, > + raead->stat_aead_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_BLKCIPHER]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_BLKCIPHER]; > + struct crypto_stat *rblk = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tCipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, > + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, > + rblk->stat_cipher_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_AKCIPHER]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_AKCIPHER]; > + struct crypto_stat *rblk = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tAkcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tSign: %u\n\tVerify: %u\n\tErrors: %u\n", > + drivername, > + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, > + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, > + rblk->stat_sign_cnt, rblk->stat_verify_cnt, > + rblk->stat_akcipher_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_CIPHER]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_CIPHER]; > + struct crypto_stat *rblk = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, > + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, > + rblk->stat_cipher_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_RNG]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_RNG]; > + struct crypto_stat *rrng = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tRNG\n\tSeed: %u\n\tGenerate: %u bytes: %llu\n\tErrors: %u\n", > + drivername, > + rrng->stat_seed_cnt, > + rrng->stat_generate_cnt, rrng->stat_generate_tlen, > + rrng->stat_rng_err_cnt); > + } else if (tb[CRYPTOCFGA_STAT_KPP]) { > + struct rtattr *rta = tb[CRYPTOCFGA_STAT_KPP]; > + struct crypto_stat *rkpp = > + (struct crypto_stat *)RTA_DATA(rta); > + printf("%s\tKPP\n\tSetsecret: %u\n\tGenerate public key: %u\n\tCompute_shared_secret: %u\n\tErrors: %u\n", > + drivername, > + rkpp->stat_setsecret_cnt, > + rkpp->stat_generate_public_key_cnt, > + rkpp->stat_compute_shared_secret_cnt, > + rkpp->stat_kpp_err_cnt); > + } else { > + fprintf(stderr, "%s is of an unknown algorithm\n", drivername); > + } > + ret = 0; > +out: > + close(sd); > + return ret; > +} > + > +int main(int argc, const char *argv[]) > +{ > + char buf[4096]; > + FILE *procfd; > + int i, lastspace; > + int ret; > + > + procfd = fopen("/proc/crypto", "r"); > + if (!procfd) { > + ret = errno; > + fprintf(stderr, "Cannot open /proc/crypto %s\n", strerror(errno)); > + return ret; > + } > + if (argc > 1) { > + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { > + printf("Usage: %s [-h|--help] display this help\n", argv[0]); > + printf("Usage: %s display all crypto statistics\n", argv[0]); > + printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv[0]); > + return 0; > + } > + for (i = 1; i < argc; i++) { > + ret = get_stat(argv[i]); > + if (ret) { > + fprintf(stderr, "Failed with %s\n", strerror(-ret)); > + return ret; > + } > + } > + return 0; > + } > + > + while (fgets(buf, sizeof(buf), procfd)) { > + if (!strncmp(buf, "driver", 6)) { > + lastspace = 0; > + i = 0; > + while (i < strlen(buf)) { > + i++; > + if (buf[i] == ' ') > + lastspace = i; > + } > + buf[strlen(buf) - 1] = '\0'; > + ret = get_stat(buf + lastspace + 1); > + if (ret) { > + fprintf(stderr, "Failed with %s\n", strerror(-ret)); > + goto out; > + } > + } > + } > +out: > + fclose(procfd); > + return ret; > +} > -- > 2.16.4 >
On 28 September 2018 at 15:13, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > On 19 September 2018 at 12:10, Corentin Labbe <clabbe@baylibre.com> wrote: >> This patch adds an userspace tool for displaying kernel crypto API >> statistics. >> >> Signed-off-by: Corentin Labbe <clabbe@baylibre.com> > > How do I actually build this thing? > Never mind.
On Fri, Sep 28, 2018 at 07:03:11PM +0200, Ard Biesheuvel wrote: > On 28 September 2018 at 15:13, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > > On 19 September 2018 at 12:10, Corentin Labbe <clabbe@baylibre.com> wrote: > >> This patch adds an userspace tool for displaying kernel crypto API > >> statistics. > >> > >> Signed-off-by: Corentin Labbe <clabbe@baylibre.com> > > > > How do I actually build this thing? > > > > Never mind. Nope you are are right, this patchset clearly lack documentation. I will send a subsequent patch with it. Furthermore, since you seems to use cryptostat, what's your usage/opinion about it and what statistic it miss. Regards
On 1 October 2018 at 09:20, LABBE Corentin <clabbe@baylibre.com> wrote: > On Fri, Sep 28, 2018 at 07:03:11PM +0200, Ard Biesheuvel wrote: >> On 28 September 2018 at 15:13, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: >> > On 19 September 2018 at 12:10, Corentin Labbe <clabbe@baylibre.com> wrote: >> >> This patch adds an userspace tool for displaying kernel crypto API >> >> statistics. >> >> >> >> Signed-off-by: Corentin Labbe <clabbe@baylibre.com> >> > >> > How do I actually build this thing? >> > >> >> Never mind. > > Nope you are are right, this patchset clearly lack documentation. > > I will send a subsequent patch with it. > > Furthermore, since you seems to use cryptostat, what's your usage/opinion about it and what statistic it miss. > To be honest, I mainly used it to check whether a certain cipher is being used at all or not, i.e., to check whether the my mac80211 interface is really using the arc4 and ccmp ciphers it allocates, or whether they are simply there as a fallback.
diff --git a/tools/crypto/getstat.c b/tools/crypto/getstat.c new file mode 100644 index 000000000000..24115173a483 --- /dev/null +++ b/tools/crypto/getstat.c @@ -0,0 +1,294 @@ +/* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller <smueller@chronox.de> */ +#include <errno.h> +#include <linux/cryptouser.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define CR_RTA(x) ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg)))) + +static int get_stat(const char *drivername) +{ + struct { + struct nlmsghdr n; + struct crypto_user_alg cru; + } req; + struct sockaddr_nl nl; + int sd = 0, ret; + socklen_t addr_len; + struct iovec iov; + struct msghdr msg; + char buf[4096]; + struct nlmsghdr *res_n = (struct nlmsghdr *)buf; + struct crypto_user_alg *cru_res = NULL; + int res_len = 0; + struct rtattr *tb[CRYPTOCFGA_MAX + 1]; + struct rtattr *rta; + struct nlmsgerr *errmsg; + + memset(&req, 0, sizeof(req)); + memset(&buf, 0, sizeof(buf)); + memset(&msg, 0, sizeof(msg)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.cru)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = CRYPTO_MSG_GETSTAT; + req.n.nlmsg_seq = time(NULL); + + strncpy(req.cru.cru_driver_name, drivername, strlen(drivername)); + + sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_CRYPTO); + if (sd < 0) { + fprintf(stderr, "Netlink error: cannot open netlink socket"); + return -errno; + } + memset(&nl, 0, sizeof(nl)); + nl.nl_family = AF_NETLINK; + if (bind(sd, (struct sockaddr *)&nl, sizeof(nl)) < 0) { + ret = -errno; + fprintf(stderr, "Netlink error: cannot bind netlink socket"); + goto out; + } + + /* sanity check that netlink socket was successfully opened */ + addr_len = sizeof(nl); + if (getsockname(sd, (struct sockaddr *)&nl, &addr_len) < 0) { + ret = -errno; + printf("Netlink error: cannot getsockname"); + goto out; + } + if (addr_len != sizeof(nl)) { + ret = -errno; + printf("Netlink error: wrong address length %d", addr_len); + goto out; + } + if (nl.nl_family != AF_NETLINK) { + ret = -errno; + printf("Netlink error: wrong address family %d", + nl.nl_family); + goto out; + } + + memset(&nl, 0, sizeof(nl)); + nl.nl_family = AF_NETLINK; + iov.iov_base = (void *)&req.n; + iov.iov_len = req.n.nlmsg_len; + msg.msg_name = &nl; + msg.msg_namelen = sizeof(nl); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + if (sendmsg(sd, &msg, 0) < 0) { + ret = -errno; + printf("Netlink error: sendmsg failed"); + goto out; + } + memset(buf, 0, sizeof(buf)); + iov.iov_base = buf; + while (1) { + iov.iov_len = sizeof(buf); + ret = recvmsg(sd, &msg, 0); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + ret = -errno; + printf("Netlink error: netlink receive error"); + goto out; + } + if (ret == 0) { + ret = -errno; + printf("Netlink error: no data"); + goto out; + } + if (ret > sizeof(buf)) { + ret = -errno; + printf("Netlink error: received too much data"); + goto out; + } + break; + } + + ret = -EFAULT; + res_len = res_n->nlmsg_len; + if (res_n->nlmsg_type == NLMSG_ERROR) { + errmsg = NLMSG_DATA(res_n); + fprintf(stderr, "Fail with %d\n", errmsg->error); + ret = errmsg->error; + goto out; + } + + if (res_n->nlmsg_type == CRYPTO_MSG_GETSTAT) { + cru_res = NLMSG_DATA(res_n); + res_len -= NLMSG_SPACE(sizeof(*cru_res)); + } + if (res_len < 0) { + printf("Netlink error: nlmsg len %d\n", res_len); + goto out; + } + + if (!cru_res) { + ret = -EFAULT; + printf("Netlink error: no cru_res\n"); + goto out; + } + + rta = CR_RTA(cru_res); + memset(tb, 0, sizeof(struct rtattr *) * (CRYPTOCFGA_MAX + 1)); + while (RTA_OK(rta, res_len)) { + if ((rta->rta_type <= CRYPTOCFGA_MAX) && (!tb[rta->rta_type])) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, res_len); + } + if (res_len) { + printf("Netlink error: unprocessed data %d", + res_len); + goto out; + } + + if (tb[CRYPTOCFGA_STAT_HASH]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_HASH]; + struct crypto_stat *rhash = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tHash\n\tHash: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rhash->stat_hash_cnt, rhash->stat_hash_tlen, + rhash->stat_hash_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_COMPRESS]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_COMPRESS]; + struct crypto_stat *rblk = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tCompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rblk->stat_compress_cnt, rblk->stat_compress_tlen, + rblk->stat_decompress_cnt, rblk->stat_decompress_tlen, + rblk->stat_compress_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_ACOMP]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_ACOMP]; + struct crypto_stat *rcomp = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tACompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rcomp->stat_compress_cnt, rcomp->stat_compress_tlen, + rcomp->stat_decompress_cnt, rcomp->stat_decompress_tlen, + rcomp->stat_compress_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_AEAD]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_AEAD]; + struct crypto_stat *raead = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tAEAD\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", + drivername, + raead->stat_encrypt_cnt, raead->stat_encrypt_tlen, + raead->stat_decrypt_cnt, raead->stat_decrypt_tlen, + raead->stat_aead_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_BLKCIPHER]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_BLKCIPHER]; + struct crypto_stat *rblk = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tCipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, + rblk->stat_cipher_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_AKCIPHER]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_AKCIPHER]; + struct crypto_stat *rblk = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tAkcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tSign: %u\n\tVerify: %u\n\tErrors: %u\n", + drivername, + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, + rblk->stat_sign_cnt, rblk->stat_verify_cnt, + rblk->stat_akcipher_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_CIPHER]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_CIPHER]; + struct crypto_stat *rblk = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen, + rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen, + rblk->stat_cipher_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_RNG]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_RNG]; + struct crypto_stat *rrng = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tRNG\n\tSeed: %u\n\tGenerate: %u bytes: %llu\n\tErrors: %u\n", + drivername, + rrng->stat_seed_cnt, + rrng->stat_generate_cnt, rrng->stat_generate_tlen, + rrng->stat_rng_err_cnt); + } else if (tb[CRYPTOCFGA_STAT_KPP]) { + struct rtattr *rta = tb[CRYPTOCFGA_STAT_KPP]; + struct crypto_stat *rkpp = + (struct crypto_stat *)RTA_DATA(rta); + printf("%s\tKPP\n\tSetsecret: %u\n\tGenerate public key: %u\n\tCompute_shared_secret: %u\n\tErrors: %u\n", + drivername, + rkpp->stat_setsecret_cnt, + rkpp->stat_generate_public_key_cnt, + rkpp->stat_compute_shared_secret_cnt, + rkpp->stat_kpp_err_cnt); + } else { + fprintf(stderr, "%s is of an unknown algorithm\n", drivername); + } + ret = 0; +out: + close(sd); + return ret; +} + +int main(int argc, const char *argv[]) +{ + char buf[4096]; + FILE *procfd; + int i, lastspace; + int ret; + + procfd = fopen("/proc/crypto", "r"); + if (!procfd) { + ret = errno; + fprintf(stderr, "Cannot open /proc/crypto %s\n", strerror(errno)); + return ret; + } + if (argc > 1) { + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { + printf("Usage: %s [-h|--help] display this help\n", argv[0]); + printf("Usage: %s display all crypto statistics\n", argv[0]); + printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv[0]); + return 0; + } + for (i = 1; i < argc; i++) { + ret = get_stat(argv[i]); + if (ret) { + fprintf(stderr, "Failed with %s\n", strerror(-ret)); + return ret; + } + } + return 0; + } + + while (fgets(buf, sizeof(buf), procfd)) { + if (!strncmp(buf, "driver", 6)) { + lastspace = 0; + i = 0; + while (i < strlen(buf)) { + i++; + if (buf[i] == ' ') + lastspace = i; + } + buf[strlen(buf) - 1] = '\0'; + ret = get_stat(buf + lastspace + 1); + if (ret) { + fprintf(stderr, "Failed with %s\n", strerror(-ret)); + goto out; + } + } + } +out: + fclose(procfd); + return ret; +}
This patch adds an userspace tool for displaying kernel crypto API statistics. Signed-off-by: Corentin Labbe <clabbe@baylibre.com> --- tools/crypto/getstat.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 tools/crypto/getstat.c