1 /* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller <smueller@chronox.de> */
3 #include <linux/cryptouser.h>
4 #include <linux/netlink.h>
5 #include <linux/rtnetlink.h>
7 #include <sys/socket.h>
14 #define CR_RTA(x) ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg))))
16 static int get_stat(const char *drivername
)
20 struct crypto_user_alg cru
;
22 struct sockaddr_nl nl
;
28 struct nlmsghdr
*res_n
= (struct nlmsghdr
*)buf
;
29 struct crypto_user_alg
*cru_res
= NULL
;
31 struct rtattr
*tb
[CRYPTOCFGA_MAX
+ 1];
33 struct nlmsgerr
*errmsg
;
35 memset(&req
, 0, sizeof(req
));
36 memset(&buf
, 0, sizeof(buf
));
37 memset(&msg
, 0, sizeof(msg
));
39 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(req
.cru
));
40 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
41 req
.n
.nlmsg_type
= CRYPTO_MSG_GETSTAT
;
42 req
.n
.nlmsg_seq
= time(NULL
);
44 strncpy(req
.cru
.cru_driver_name
, drivername
, strlen(drivername
));
46 sd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_CRYPTO
);
48 fprintf(stderr
, "Netlink error: cannot open netlink socket");
51 memset(&nl
, 0, sizeof(nl
));
52 nl
.nl_family
= AF_NETLINK
;
53 if (bind(sd
, (struct sockaddr
*)&nl
, sizeof(nl
)) < 0) {
55 fprintf(stderr
, "Netlink error: cannot bind netlink socket");
59 /* sanity check that netlink socket was successfully opened */
60 addr_len
= sizeof(nl
);
61 if (getsockname(sd
, (struct sockaddr
*)&nl
, &addr_len
) < 0) {
63 printf("Netlink error: cannot getsockname");
66 if (addr_len
!= sizeof(nl
)) {
68 printf("Netlink error: wrong address length %d", addr_len
);
71 if (nl
.nl_family
!= AF_NETLINK
) {
73 printf("Netlink error: wrong address family %d",
78 memset(&nl
, 0, sizeof(nl
));
79 nl
.nl_family
= AF_NETLINK
;
80 iov
.iov_base
= (void *)&req
.n
;
81 iov
.iov_len
= req
.n
.nlmsg_len
;
83 msg
.msg_namelen
= sizeof(nl
);
86 if (sendmsg(sd
, &msg
, 0) < 0) {
88 printf("Netlink error: sendmsg failed");
91 memset(buf
, 0, sizeof(buf
));
94 iov
.iov_len
= sizeof(buf
);
95 ret
= recvmsg(sd
, &msg
, 0);
97 if (errno
== EINTR
|| errno
== EAGAIN
)
100 printf("Netlink error: netlink receive error");
105 printf("Netlink error: no data");
108 if (ret
> sizeof(buf
)) {
110 printf("Netlink error: received too much data");
117 res_len
= res_n
->nlmsg_len
;
118 if (res_n
->nlmsg_type
== NLMSG_ERROR
) {
119 errmsg
= NLMSG_DATA(res_n
);
120 fprintf(stderr
, "Fail with %d\n", errmsg
->error
);
125 if (res_n
->nlmsg_type
== CRYPTO_MSG_GETSTAT
) {
126 cru_res
= NLMSG_DATA(res_n
);
127 res_len
-= NLMSG_SPACE(sizeof(*cru_res
));
130 printf("Netlink error: nlmsg len %d\n", res_len
);
136 printf("Netlink error: no cru_res\n");
140 rta
= CR_RTA(cru_res
);
141 memset(tb
, 0, sizeof(struct rtattr
*) * (CRYPTOCFGA_MAX
+ 1));
142 while (RTA_OK(rta
, res_len
)) {
143 if ((rta
->rta_type
<= CRYPTOCFGA_MAX
) && (!tb
[rta
->rta_type
]))
144 tb
[rta
->rta_type
] = rta
;
145 rta
= RTA_NEXT(rta
, res_len
);
148 printf("Netlink error: unprocessed data %d",
153 if (tb
[CRYPTOCFGA_STAT_HASH
]) {
154 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_HASH
];
155 struct crypto_stat
*rhash
=
156 (struct crypto_stat
*)RTA_DATA(rta
);
157 printf("%s\tHash\n\tHash: %u bytes: %llu\n\tErrors: %u\n",
159 rhash
->stat_hash_cnt
, rhash
->stat_hash_tlen
,
160 rhash
->stat_hash_err_cnt
);
161 } else if (tb
[CRYPTOCFGA_STAT_COMPRESS
]) {
162 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_COMPRESS
];
163 struct crypto_stat
*rblk
=
164 (struct crypto_stat
*)RTA_DATA(rta
);
165 printf("%s\tCompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n",
167 rblk
->stat_compress_cnt
, rblk
->stat_compress_tlen
,
168 rblk
->stat_decompress_cnt
, rblk
->stat_decompress_tlen
,
169 rblk
->stat_compress_err_cnt
);
170 } else if (tb
[CRYPTOCFGA_STAT_ACOMP
]) {
171 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_ACOMP
];
172 struct crypto_stat
*rcomp
=
173 (struct crypto_stat
*)RTA_DATA(rta
);
174 printf("%s\tACompress\n\tCompress: %u bytes: %llu\n\tDecompress: %u bytes: %llu\n\tErrors: %u\n",
176 rcomp
->stat_compress_cnt
, rcomp
->stat_compress_tlen
,
177 rcomp
->stat_decompress_cnt
, rcomp
->stat_decompress_tlen
,
178 rcomp
->stat_compress_err_cnt
);
179 } else if (tb
[CRYPTOCFGA_STAT_AEAD
]) {
180 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_AEAD
];
181 struct crypto_stat
*raead
=
182 (struct crypto_stat
*)RTA_DATA(rta
);
183 printf("%s\tAEAD\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
185 raead
->stat_encrypt_cnt
, raead
->stat_encrypt_tlen
,
186 raead
->stat_decrypt_cnt
, raead
->stat_decrypt_tlen
,
187 raead
->stat_aead_err_cnt
);
188 } else if (tb
[CRYPTOCFGA_STAT_BLKCIPHER
]) {
189 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_BLKCIPHER
];
190 struct crypto_stat
*rblk
=
191 (struct crypto_stat
*)RTA_DATA(rta
);
192 printf("%s\tCipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
194 rblk
->stat_encrypt_cnt
, rblk
->stat_encrypt_tlen
,
195 rblk
->stat_decrypt_cnt
, rblk
->stat_decrypt_tlen
,
196 rblk
->stat_cipher_err_cnt
);
197 } else if (tb
[CRYPTOCFGA_STAT_AKCIPHER
]) {
198 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_AKCIPHER
];
199 struct crypto_stat
*rblk
=
200 (struct crypto_stat
*)RTA_DATA(rta
);
201 printf("%s\tAkcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tSign: %u\n\tVerify: %u\n\tErrors: %u\n",
203 rblk
->stat_encrypt_cnt
, rblk
->stat_encrypt_tlen
,
204 rblk
->stat_decrypt_cnt
, rblk
->stat_decrypt_tlen
,
205 rblk
->stat_sign_cnt
, rblk
->stat_verify_cnt
,
206 rblk
->stat_akcipher_err_cnt
);
207 } else if (tb
[CRYPTOCFGA_STAT_CIPHER
]) {
208 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_CIPHER
];
209 struct crypto_stat
*rblk
=
210 (struct crypto_stat
*)RTA_DATA(rta
);
211 printf("%s\tcipher\n\tEncrypt: %u bytes: %llu\n\tDecrypt: %u bytes: %llu\n\tErrors: %u\n",
213 rblk
->stat_encrypt_cnt
, rblk
->stat_encrypt_tlen
,
214 rblk
->stat_decrypt_cnt
, rblk
->stat_decrypt_tlen
,
215 rblk
->stat_cipher_err_cnt
);
216 } else if (tb
[CRYPTOCFGA_STAT_RNG
]) {
217 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_RNG
];
218 struct crypto_stat
*rrng
=
219 (struct crypto_stat
*)RTA_DATA(rta
);
220 printf("%s\tRNG\n\tSeed: %u\n\tGenerate: %u bytes: %llu\n\tErrors: %u\n",
223 rrng
->stat_generate_cnt
, rrng
->stat_generate_tlen
,
224 rrng
->stat_rng_err_cnt
);
225 } else if (tb
[CRYPTOCFGA_STAT_KPP
]) {
226 struct rtattr
*rta
= tb
[CRYPTOCFGA_STAT_KPP
];
227 struct crypto_stat
*rkpp
=
228 (struct crypto_stat
*)RTA_DATA(rta
);
229 printf("%s\tKPP\n\tSetsecret: %u\n\tGenerate public key: %u\n\tCompute_shared_secret: %u\n\tErrors: %u\n",
231 rkpp
->stat_setsecret_cnt
,
232 rkpp
->stat_generate_public_key_cnt
,
233 rkpp
->stat_compute_shared_secret_cnt
,
234 rkpp
->stat_kpp_err_cnt
);
236 fprintf(stderr
, "%s is of an unknown algorithm\n", drivername
);
244 int main(int argc
, const char *argv
[])
251 procfd
= fopen("/proc/crypto", "r");
254 fprintf(stderr
, "Cannot open /proc/crypto %s\n", strerror(errno
));
258 if (!strcmp(argv
[1], "-h") || !strcmp(argv
[1], "--help")) {
259 printf("Usage: %s [-h|--help] display this help\n", argv
[0]);
260 printf("Usage: %s display all crypto statistics\n", argv
[0]);
261 printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv
[0]);
264 for (i
= 1; i
< argc
; i
++) {
265 ret
= get_stat(argv
[i
]);
267 fprintf(stderr
, "Failed with %s\n", strerror(-ret
));
274 while (fgets(buf
, sizeof(buf
), procfd
)) {
275 if (!strncmp(buf
, "driver", 6)) {
278 while (i
< strlen(buf
)) {
283 buf
[strlen(buf
) - 1] = '\0';
284 ret
= get_stat(buf
+ lastspace
+ 1);
286 fprintf(stderr
, "Failed with %s\n", strerror(-ret
));