0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/completion.h>
0010 #include <crypto/internal/rng.h>
0011 #include "compat.h"
0012 #include "regs.h"
0013 #include "intern.h"
0014 #include "desc_constr.h"
0015 #include "jr.h"
0016 #include "error.h"
0017
0018
0019
0020
0021 #define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \
0022 CAAM_CMD_SZ + \
0023 CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
0024
0025
0026 struct caam_prng_ctx {
0027 int err;
0028 struct completion done;
0029 };
0030
0031 struct caam_prng_alg {
0032 struct rng_alg rng;
0033 bool registered;
0034 };
0035
0036 static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err,
0037 void *context)
0038 {
0039 struct caam_prng_ctx *jctx = context;
0040
0041 jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0;
0042
0043 complete(&jctx->done);
0044 }
0045
0046 static u32 *caam_init_reseed_desc(u32 *desc)
0047 {
0048 init_job_desc(desc, 0);
0049
0050 append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
0051 OP_ALG_AS_FINALIZE);
0052
0053 print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS,
0054 16, 4, desc, desc_bytes(desc), 1);
0055
0056 return desc;
0057 }
0058
0059 static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len)
0060 {
0061 init_job_desc(desc, 0);
0062
0063 append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
0064
0065 append_fifo_store(desc, dst_dma,
0066 len, FIFOST_TYPE_RNGSTORE);
0067
0068 print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS,
0069 16, 4, desc, desc_bytes(desc), 1);
0070
0071 return desc;
0072 }
0073
0074 static int caam_prng_generate(struct crypto_rng *tfm,
0075 const u8 *src, unsigned int slen,
0076 u8 *dst, unsigned int dlen)
0077 {
0078 struct caam_prng_ctx ctx;
0079 struct device *jrdev;
0080 dma_addr_t dst_dma;
0081 u32 *desc;
0082 u8 *buf;
0083 int ret;
0084
0085 buf = kzalloc(dlen, GFP_KERNEL);
0086 if (!buf)
0087 return -ENOMEM;
0088
0089 jrdev = caam_jr_alloc();
0090 ret = PTR_ERR_OR_ZERO(jrdev);
0091 if (ret) {
0092 pr_err("Job Ring Device allocation failed\n");
0093 kfree(buf);
0094 return ret;
0095 }
0096
0097 desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA);
0098 if (!desc) {
0099 ret = -ENOMEM;
0100 goto out1;
0101 }
0102
0103 dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE);
0104 if (dma_mapping_error(jrdev, dst_dma)) {
0105 dev_err(jrdev, "Failed to map destination buffer memory\n");
0106 ret = -ENOMEM;
0107 goto out;
0108 }
0109
0110 init_completion(&ctx.done);
0111 ret = caam_jr_enqueue(jrdev,
0112 caam_init_prng_desc(desc, dst_dma, dlen),
0113 caam_prng_done, &ctx);
0114
0115 if (ret == -EINPROGRESS) {
0116 wait_for_completion(&ctx.done);
0117 ret = ctx.err;
0118 }
0119
0120 dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE);
0121
0122 if (!ret)
0123 memcpy(dst, buf, dlen);
0124 out:
0125 kfree(desc);
0126 out1:
0127 caam_jr_free(jrdev);
0128 kfree(buf);
0129 return ret;
0130 }
0131
0132 static void caam_prng_exit(struct crypto_tfm *tfm) {}
0133
0134 static int caam_prng_init(struct crypto_tfm *tfm)
0135 {
0136 return 0;
0137 }
0138
0139 static int caam_prng_seed(struct crypto_rng *tfm,
0140 const u8 *seed, unsigned int slen)
0141 {
0142 struct caam_prng_ctx ctx;
0143 struct device *jrdev;
0144 u32 *desc;
0145 int ret;
0146
0147 if (slen) {
0148 pr_err("Seed length should be zero\n");
0149 return -EINVAL;
0150 }
0151
0152 jrdev = caam_jr_alloc();
0153 ret = PTR_ERR_OR_ZERO(jrdev);
0154 if (ret) {
0155 pr_err("Job Ring Device allocation failed\n");
0156 return ret;
0157 }
0158
0159 desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL | GFP_DMA);
0160 if (!desc) {
0161 caam_jr_free(jrdev);
0162 return -ENOMEM;
0163 }
0164
0165 init_completion(&ctx.done);
0166 ret = caam_jr_enqueue(jrdev,
0167 caam_init_reseed_desc(desc),
0168 caam_prng_done, &ctx);
0169
0170 if (ret == -EINPROGRESS) {
0171 wait_for_completion(&ctx.done);
0172 ret = ctx.err;
0173 }
0174
0175 kfree(desc);
0176 caam_jr_free(jrdev);
0177 return ret;
0178 }
0179
0180 static struct caam_prng_alg caam_prng_alg = {
0181 .rng = {
0182 .generate = caam_prng_generate,
0183 .seed = caam_prng_seed,
0184 .seedsize = 0,
0185 .base = {
0186 .cra_name = "stdrng",
0187 .cra_driver_name = "prng-caam",
0188 .cra_priority = 500,
0189 .cra_ctxsize = sizeof(struct caam_prng_ctx),
0190 .cra_module = THIS_MODULE,
0191 .cra_init = caam_prng_init,
0192 .cra_exit = caam_prng_exit,
0193 },
0194 }
0195 };
0196
0197 void caam_prng_unregister(void *data)
0198 {
0199 if (caam_prng_alg.registered)
0200 crypto_unregister_rng(&caam_prng_alg.rng);
0201 }
0202
0203 int caam_prng_register(struct device *ctrldev)
0204 {
0205 struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
0206 u32 rng_inst;
0207 int ret = 0;
0208
0209
0210 if (priv->era < 10)
0211 rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
0212 CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
0213 else
0214 rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
0215
0216 if (!rng_inst) {
0217 dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n");
0218 return ret;
0219 }
0220
0221 ret = crypto_register_rng(&caam_prng_alg.rng);
0222 if (ret) {
0223 dev_err(ctrldev,
0224 "couldn't register rng crypto alg: %d\n",
0225 ret);
0226 return ret;
0227 }
0228
0229 caam_prng_alg.registered = true;
0230
0231 dev_info(ctrldev,
0232 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name);
0233
0234 return 0;
0235 }