123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /* 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;
- }
|