Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Driver to expose SEC4 PRNG via crypto RNG API
0004  *
0005  * Copyright 2022 NXP
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  * Length of used descriptors, see caam_init_desc()
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 /* prng per-device context */
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); /* + 1 cmd_sz */
0049     /* Generate random bytes: + 1 cmd_sz */
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); /* + 1 cmd_sz */
0062     /* Generate random bytes: + 1 cmd_sz */
0063     append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
0064     /* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
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     /* Check for available RNG blocks before registration */
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 }