0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/errno.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/seq_file.h>
0013 #include <linux/slab.h>
0014 #include <linux/string.h>
0015 #include <linux/crypto.h>
0016 #include <crypto/algapi.h>
0017 #include <linux/cryptouser.h>
0018 #include <linux/compiler.h>
0019 #include <net/netlink.h>
0020 #include <crypto/internal/acompress.h>
0021 #include <crypto/internal/scompress.h>
0022 #include "internal.h"
0023
0024 static const struct crypto_type crypto_acomp_type;
0025
0026 #ifdef CONFIG_NET
0027 static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
0028 {
0029 struct crypto_report_acomp racomp;
0030
0031 memset(&racomp, 0, sizeof(racomp));
0032
0033 strscpy(racomp.type, "acomp", sizeof(racomp.type));
0034
0035 return nla_put(skb, CRYPTOCFGA_REPORT_ACOMP, sizeof(racomp), &racomp);
0036 }
0037 #else
0038 static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
0039 {
0040 return -ENOSYS;
0041 }
0042 #endif
0043
0044 static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
0045 __maybe_unused;
0046
0047 static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
0048 {
0049 seq_puts(m, "type : acomp\n");
0050 }
0051
0052 static void crypto_acomp_exit_tfm(struct crypto_tfm *tfm)
0053 {
0054 struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
0055 struct acomp_alg *alg = crypto_acomp_alg(acomp);
0056
0057 alg->exit(acomp);
0058 }
0059
0060 static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
0061 {
0062 struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
0063 struct acomp_alg *alg = crypto_acomp_alg(acomp);
0064
0065 if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
0066 return crypto_init_scomp_ops_async(tfm);
0067
0068 acomp->compress = alg->compress;
0069 acomp->decompress = alg->decompress;
0070 acomp->dst_free = alg->dst_free;
0071 acomp->reqsize = alg->reqsize;
0072
0073 if (alg->exit)
0074 acomp->base.exit = crypto_acomp_exit_tfm;
0075
0076 if (alg->init)
0077 return alg->init(acomp);
0078
0079 return 0;
0080 }
0081
0082 static unsigned int crypto_acomp_extsize(struct crypto_alg *alg)
0083 {
0084 int extsize = crypto_alg_extsize(alg);
0085
0086 if (alg->cra_type != &crypto_acomp_type)
0087 extsize += sizeof(struct crypto_scomp *);
0088
0089 return extsize;
0090 }
0091
0092 static const struct crypto_type crypto_acomp_type = {
0093 .extsize = crypto_acomp_extsize,
0094 .init_tfm = crypto_acomp_init_tfm,
0095 #ifdef CONFIG_PROC_FS
0096 .show = crypto_acomp_show,
0097 #endif
0098 .report = crypto_acomp_report,
0099 .maskclear = ~CRYPTO_ALG_TYPE_MASK,
0100 .maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK,
0101 .type = CRYPTO_ALG_TYPE_ACOMPRESS,
0102 .tfmsize = offsetof(struct crypto_acomp, base),
0103 };
0104
0105 struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
0106 u32 mask)
0107 {
0108 return crypto_alloc_tfm(alg_name, &crypto_acomp_type, type, mask);
0109 }
0110 EXPORT_SYMBOL_GPL(crypto_alloc_acomp);
0111
0112 struct crypto_acomp *crypto_alloc_acomp_node(const char *alg_name, u32 type,
0113 u32 mask, int node)
0114 {
0115 return crypto_alloc_tfm_node(alg_name, &crypto_acomp_type, type, mask,
0116 node);
0117 }
0118 EXPORT_SYMBOL_GPL(crypto_alloc_acomp_node);
0119
0120 struct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp)
0121 {
0122 struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
0123 struct acomp_req *req;
0124
0125 req = __acomp_request_alloc(acomp);
0126 if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type))
0127 return crypto_acomp_scomp_alloc_ctx(req);
0128
0129 return req;
0130 }
0131 EXPORT_SYMBOL_GPL(acomp_request_alloc);
0132
0133 void acomp_request_free(struct acomp_req *req)
0134 {
0135 struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
0136 struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
0137
0138 if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
0139 crypto_acomp_scomp_free_ctx(req);
0140
0141 if (req->flags & CRYPTO_ACOMP_ALLOC_OUTPUT) {
0142 acomp->dst_free(req->dst);
0143 req->dst = NULL;
0144 }
0145
0146 __acomp_request_free(req);
0147 }
0148 EXPORT_SYMBOL_GPL(acomp_request_free);
0149
0150 int crypto_register_acomp(struct acomp_alg *alg)
0151 {
0152 struct crypto_alg *base = &alg->base;
0153
0154 base->cra_type = &crypto_acomp_type;
0155 base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
0156 base->cra_flags |= CRYPTO_ALG_TYPE_ACOMPRESS;
0157
0158 return crypto_register_alg(base);
0159 }
0160 EXPORT_SYMBOL_GPL(crypto_register_acomp);
0161
0162 void crypto_unregister_acomp(struct acomp_alg *alg)
0163 {
0164 crypto_unregister_alg(&alg->base);
0165 }
0166 EXPORT_SYMBOL_GPL(crypto_unregister_acomp);
0167
0168 int crypto_register_acomps(struct acomp_alg *algs, int count)
0169 {
0170 int i, ret;
0171
0172 for (i = 0; i < count; i++) {
0173 ret = crypto_register_acomp(&algs[i]);
0174 if (ret)
0175 goto err;
0176 }
0177
0178 return 0;
0179
0180 err:
0181 for (--i; i >= 0; --i)
0182 crypto_unregister_acomp(&algs[i]);
0183
0184 return ret;
0185 }
0186 EXPORT_SYMBOL_GPL(crypto_register_acomps);
0187
0188 void crypto_unregister_acomps(struct acomp_alg *algs, int count)
0189 {
0190 int i;
0191
0192 for (i = count - 1; i >= 0; --i)
0193 crypto_unregister_acomp(&algs[i]);
0194 }
0195 EXPORT_SYMBOL_GPL(crypto_unregister_acomps);
0196
0197 MODULE_LICENSE("GPL");
0198 MODULE_DESCRIPTION("Asynchronous compression type");