cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

crypto_user_stat.c (9880B)


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