crypto_user_stat.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Crypto user configuration API.
  4. *
  5. * Copyright (C) 2017-2018 Corentin Labbe <clabbe@baylibre.com>
  6. *
  7. */
  8. #include <linux/crypto.h>
  9. #include <linux/cryptouser.h>
  10. #include <linux/sched.h>
  11. #include <net/netlink.h>
  12. #include <net/sock.h>
  13. #include <crypto/internal/skcipher.h>
  14. #include <crypto/internal/rng.h>
  15. #include <crypto/akcipher.h>
  16. #include <crypto/kpp.h>
  17. #include <crypto/internal/cryptouser.h>
  18. #include "internal.h"
  19. #define null_terminated(x) (strnlen(x, sizeof(x)) < sizeof(x))
  20. struct crypto_dump_info {
  21. struct sk_buff *in_skb;
  22. struct sk_buff *out_skb;
  23. u32 nlmsg_seq;
  24. u16 nlmsg_flags;
  25. };
  26. static int crypto_report_aead(struct sk_buff *skb, struct crypto_alg *alg)
  27. {
  28. struct crypto_stat_aead raead;
  29. memset(&raead, 0, sizeof(raead));
  30. strscpy(raead.type, "aead", sizeof(raead.type));
  31. raead.stat_encrypt_cnt = atomic64_read(&alg->stats.aead.encrypt_cnt);
  32. raead.stat_encrypt_tlen = atomic64_read(&alg->stats.aead.encrypt_tlen);
  33. raead.stat_decrypt_cnt = atomic64_read(&alg->stats.aead.decrypt_cnt);
  34. raead.stat_decrypt_tlen = atomic64_read(&alg->stats.aead.decrypt_tlen);
  35. raead.stat_err_cnt = atomic64_read(&alg->stats.aead.err_cnt);
  36. return nla_put(skb, CRYPTOCFGA_STAT_AEAD, sizeof(raead), &raead);
  37. }
  38. static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
  39. {
  40. struct crypto_stat_cipher rcipher;
  41. memset(&rcipher, 0, sizeof(rcipher));
  42. strscpy(rcipher.type, "cipher", sizeof(rcipher.type));
  43. rcipher.stat_encrypt_cnt = atomic64_read(&alg->stats.cipher.encrypt_cnt);
  44. rcipher.stat_encrypt_tlen = atomic64_read(&alg->stats.cipher.encrypt_tlen);
  45. rcipher.stat_decrypt_cnt = atomic64_read(&alg->stats.cipher.decrypt_cnt);
  46. rcipher.stat_decrypt_tlen = atomic64_read(&alg->stats.cipher.decrypt_tlen);
  47. rcipher.stat_err_cnt = atomic64_read(&alg->stats.cipher.err_cnt);
  48. return nla_put(skb, CRYPTOCFGA_STAT_CIPHER, sizeof(rcipher), &rcipher);
  49. }
  50. static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
  51. {
  52. struct crypto_stat_compress rcomp;
  53. memset(&rcomp, 0, sizeof(rcomp));
  54. strscpy(rcomp.type, "compression", sizeof(rcomp.type));
  55. rcomp.stat_compress_cnt = atomic64_read(&alg->stats.compress.compress_cnt);
  56. rcomp.stat_compress_tlen = atomic64_read(&alg->stats.compress.compress_tlen);
  57. rcomp.stat_decompress_cnt = atomic64_read(&alg->stats.compress.decompress_cnt);
  58. rcomp.stat_decompress_tlen = atomic64_read(&alg->stats.compress.decompress_tlen);
  59. rcomp.stat_err_cnt = atomic64_read(&alg->stats.compress.err_cnt);
  60. return nla_put(skb, CRYPTOCFGA_STAT_COMPRESS, sizeof(rcomp), &rcomp);
  61. }
  62. static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
  63. {
  64. struct crypto_stat_compress racomp;
  65. memset(&racomp, 0, sizeof(racomp));
  66. strscpy(racomp.type, "acomp", sizeof(racomp.type));
  67. racomp.stat_compress_cnt = atomic64_read(&alg->stats.compress.compress_cnt);
  68. racomp.stat_compress_tlen = atomic64_read(&alg->stats.compress.compress_tlen);
  69. racomp.stat_decompress_cnt = atomic64_read(&alg->stats.compress.decompress_cnt);
  70. racomp.stat_decompress_tlen = atomic64_read(&alg->stats.compress.decompress_tlen);
  71. racomp.stat_err_cnt = atomic64_read(&alg->stats.compress.err_cnt);
  72. return nla_put(skb, CRYPTOCFGA_STAT_ACOMP, sizeof(racomp), &racomp);
  73. }
  74. static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
  75. {
  76. struct crypto_stat_akcipher rakcipher;
  77. memset(&rakcipher, 0, sizeof(rakcipher));
  78. strscpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
  79. rakcipher.stat_encrypt_cnt = atomic64_read(&alg->stats.akcipher.encrypt_cnt);
  80. rakcipher.stat_encrypt_tlen = atomic64_read(&alg->stats.akcipher.encrypt_tlen);
  81. rakcipher.stat_decrypt_cnt = atomic64_read(&alg->stats.akcipher.decrypt_cnt);
  82. rakcipher.stat_decrypt_tlen = atomic64_read(&alg->stats.akcipher.decrypt_tlen);
  83. rakcipher.stat_sign_cnt = atomic64_read(&alg->stats.akcipher.sign_cnt);
  84. rakcipher.stat_verify_cnt = atomic64_read(&alg->stats.akcipher.verify_cnt);
  85. rakcipher.stat_err_cnt = atomic64_read(&alg->stats.akcipher.err_cnt);
  86. return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER,
  87. sizeof(rakcipher), &rakcipher);
  88. }
  89. static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
  90. {
  91. struct crypto_stat_kpp rkpp;
  92. memset(&rkpp, 0, sizeof(rkpp));
  93. strscpy(rkpp.type, "kpp", sizeof(rkpp.type));
  94. rkpp.stat_setsecret_cnt = atomic64_read(&alg->stats.kpp.setsecret_cnt);
  95. rkpp.stat_generate_public_key_cnt = atomic64_read(&alg->stats.kpp.generate_public_key_cnt);
  96. rkpp.stat_compute_shared_secret_cnt = atomic64_read(&alg->stats.kpp.compute_shared_secret_cnt);
  97. rkpp.stat_err_cnt = atomic64_read(&alg->stats.kpp.err_cnt);
  98. return nla_put(skb, CRYPTOCFGA_STAT_KPP, sizeof(rkpp), &rkpp);
  99. }
  100. static int crypto_report_ahash(struct sk_buff *skb, struct crypto_alg *alg)
  101. {
  102. struct crypto_stat_hash rhash;
  103. memset(&rhash, 0, sizeof(rhash));
  104. strscpy(rhash.type, "ahash", sizeof(rhash.type));
  105. rhash.stat_hash_cnt = atomic64_read(&alg->stats.hash.hash_cnt);
  106. rhash.stat_hash_tlen = atomic64_read(&alg->stats.hash.hash_tlen);
  107. rhash.stat_err_cnt = atomic64_read(&alg->stats.hash.err_cnt);
  108. return nla_put(skb, CRYPTOCFGA_STAT_HASH, sizeof(rhash), &rhash);
  109. }
  110. static int crypto_report_shash(struct sk_buff *skb, struct crypto_alg *alg)
  111. {
  112. struct crypto_stat_hash rhash;
  113. memset(&rhash, 0, sizeof(rhash));
  114. strscpy(rhash.type, "shash", sizeof(rhash.type));
  115. rhash.stat_hash_cnt = atomic64_read(&alg->stats.hash.hash_cnt);
  116. rhash.stat_hash_tlen = atomic64_read(&alg->stats.hash.hash_tlen);
  117. rhash.stat_err_cnt = atomic64_read(&alg->stats.hash.err_cnt);
  118. return nla_put(skb, CRYPTOCFGA_STAT_HASH, sizeof(rhash), &rhash);
  119. }
  120. static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
  121. {
  122. struct crypto_stat_rng rrng;
  123. memset(&rrng, 0, sizeof(rrng));
  124. strscpy(rrng.type, "rng", sizeof(rrng.type));
  125. rrng.stat_generate_cnt = atomic64_read(&alg->stats.rng.generate_cnt);
  126. rrng.stat_generate_tlen = atomic64_read(&alg->stats.rng.generate_tlen);
  127. rrng.stat_seed_cnt = atomic64_read(&alg->stats.rng.seed_cnt);
  128. rrng.stat_err_cnt = atomic64_read(&alg->stats.rng.err_cnt);
  129. return nla_put(skb, CRYPTOCFGA_STAT_RNG, sizeof(rrng), &rrng);
  130. }
  131. static int crypto_reportstat_one(struct crypto_alg *alg,
  132. struct crypto_user_alg *ualg,
  133. struct sk_buff *skb)
  134. {
  135. memset(ualg, 0, sizeof(*ualg));
  136. strscpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
  137. strscpy(ualg->cru_driver_name, alg->cra_driver_name,
  138. sizeof(ualg->cru_driver_name));
  139. strscpy(ualg->cru_module_name, module_name(alg->cra_module),
  140. sizeof(ualg->cru_module_name));
  141. ualg->cru_type = 0;
  142. ualg->cru_mask = 0;
  143. ualg->cru_flags = alg->cra_flags;
  144. ualg->cru_refcnt = refcount_read(&alg->cra_refcnt);
  145. if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
  146. goto nla_put_failure;
  147. if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
  148. struct crypto_stat_larval rl;
  149. memset(&rl, 0, sizeof(rl));
  150. strscpy(rl.type, "larval", sizeof(rl.type));
  151. if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL, sizeof(rl), &rl))
  152. goto nla_put_failure;
  153. goto out;
  154. }
  155. switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
  156. case CRYPTO_ALG_TYPE_AEAD:
  157. if (crypto_report_aead(skb, alg))
  158. goto nla_put_failure;
  159. break;
  160. case CRYPTO_ALG_TYPE_SKCIPHER:
  161. if (crypto_report_cipher(skb, alg))
  162. goto nla_put_failure;
  163. break;
  164. case CRYPTO_ALG_TYPE_CIPHER:
  165. if (crypto_report_cipher(skb, alg))
  166. goto nla_put_failure;
  167. break;
  168. case CRYPTO_ALG_TYPE_COMPRESS:
  169. if (crypto_report_comp(skb, alg))
  170. goto nla_put_failure;
  171. break;
  172. case CRYPTO_ALG_TYPE_ACOMPRESS:
  173. if (crypto_report_acomp(skb, alg))
  174. goto nla_put_failure;
  175. break;
  176. case CRYPTO_ALG_TYPE_SCOMPRESS:
  177. if (crypto_report_acomp(skb, alg))
  178. goto nla_put_failure;
  179. break;
  180. case CRYPTO_ALG_TYPE_AKCIPHER:
  181. if (crypto_report_akcipher(skb, alg))
  182. goto nla_put_failure;
  183. break;
  184. case CRYPTO_ALG_TYPE_KPP:
  185. if (crypto_report_kpp(skb, alg))
  186. goto nla_put_failure;
  187. break;
  188. case CRYPTO_ALG_TYPE_AHASH:
  189. if (crypto_report_ahash(skb, alg))
  190. goto nla_put_failure;
  191. break;
  192. case CRYPTO_ALG_TYPE_HASH:
  193. if (crypto_report_shash(skb, alg))
  194. goto nla_put_failure;
  195. break;
  196. case CRYPTO_ALG_TYPE_RNG:
  197. if (crypto_report_rng(skb, alg))
  198. goto nla_put_failure;
  199. break;
  200. default:
  201. pr_err("ERROR: Unhandled alg %d in %s\n",
  202. alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL),
  203. __func__);
  204. }
  205. out:
  206. return 0;
  207. nla_put_failure:
  208. return -EMSGSIZE;
  209. }
  210. static int crypto_reportstat_alg(struct crypto_alg *alg,
  211. struct crypto_dump_info *info)
  212. {
  213. struct sk_buff *in_skb = info->in_skb;
  214. struct sk_buff *skb = info->out_skb;
  215. struct nlmsghdr *nlh;
  216. struct crypto_user_alg *ualg;
  217. int err = 0;
  218. nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
  219. CRYPTO_MSG_GETSTAT, sizeof(*ualg), info->nlmsg_flags);
  220. if (!nlh) {
  221. err = -EMSGSIZE;
  222. goto out;
  223. }
  224. ualg = nlmsg_data(nlh);
  225. err = crypto_reportstat_one(alg, ualg, skb);
  226. if (err) {
  227. nlmsg_cancel(skb, nlh);
  228. goto out;
  229. }
  230. nlmsg_end(skb, nlh);
  231. out:
  232. return err;
  233. }
  234. int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
  235. struct nlattr **attrs)
  236. {
  237. struct net *net = sock_net(in_skb->sk);
  238. struct crypto_user_alg *p = nlmsg_data(in_nlh);
  239. struct crypto_alg *alg;
  240. struct sk_buff *skb;
  241. struct crypto_dump_info info;
  242. int err;
  243. if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
  244. return -EINVAL;
  245. alg = crypto_alg_match(p, 0);
  246. if (!alg)
  247. return -ENOENT;
  248. err = -ENOMEM;
  249. skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
  250. if (!skb)
  251. goto drop_alg;
  252. info.in_skb = in_skb;
  253. info.out_skb = skb;
  254. info.nlmsg_seq = in_nlh->nlmsg_seq;
  255. info.nlmsg_flags = 0;
  256. err = crypto_reportstat_alg(alg, &info);
  257. drop_alg:
  258. crypto_mod_put(alg);
  259. if (err) {
  260. kfree_skb(skb);
  261. return err;
  262. }
  263. return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
  264. }
  265. MODULE_LICENSE("GPL");