1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Driver to expose SEC4 PRNG via crypto RNG API 4 * 5 * Copyright 2022 NXP 6 * 7 */ 8 9 #include <linux/completion.h> 10 #include <crypto/internal/rng.h> 11 #include <linux/dma-mapping.h> 12 #include <linux/kernel.h> 13 #include "compat.h" 14 #include "regs.h" 15 #include "intern.h" 16 #include "desc_constr.h" 17 #include "jr.h" 18 #include "error.h" 19 20 /* 21 * Length of used descriptors, see caam_init_desc() 22 */ 23 #define CAAM_PRNG_MAX_DESC_LEN (CAAM_CMD_SZ + \ 24 CAAM_CMD_SZ + \ 25 CAAM_CMD_SZ + CAAM_PTR_SZ_MAX) 26 27 /* prng per-device context */ 28 struct caam_prng_ctx { 29 int err; 30 struct completion done; 31 }; 32 33 struct caam_prng_alg { 34 struct rng_alg rng; 35 bool registered; 36 }; 37 38 static void caam_prng_done(struct device *jrdev, u32 *desc, u32 err, 39 void *context) 40 { 41 struct caam_prng_ctx *jctx = context; 42 43 jctx->err = err ? caam_jr_strstatus(jrdev, err) : 0; 44 45 complete(&jctx->done); 46 } 47 48 static u32 *caam_init_reseed_desc(u32 *desc) 49 { 50 init_job_desc(desc, 0); /* + 1 cmd_sz */ 51 /* Generate random bytes: + 1 cmd_sz */ 52 append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | 53 OP_ALG_AS_FINALIZE); 54 55 print_hex_dump_debug("prng reseed desc@: ", DUMP_PREFIX_ADDRESS, 56 16, 4, desc, desc_bytes(desc), 1); 57 58 return desc; 59 } 60 61 static u32 *caam_init_prng_desc(u32 *desc, dma_addr_t dst_dma, u32 len) 62 { 63 init_job_desc(desc, 0); /* + 1 cmd_sz */ 64 /* Generate random bytes: + 1 cmd_sz */ 65 append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); 66 /* Store bytes: + 1 cmd_sz + caam_ptr_sz */ 67 append_fifo_store(desc, dst_dma, 68 len, FIFOST_TYPE_RNGSTORE); 69 70 print_hex_dump_debug("prng job desc@: ", DUMP_PREFIX_ADDRESS, 71 16, 4, desc, desc_bytes(desc), 1); 72 73 return desc; 74 } 75 76 static int caam_prng_generate(struct crypto_rng *tfm, 77 const u8 *src, unsigned int slen, 78 u8 *dst, unsigned int dlen) 79 { 80 unsigned int aligned_dlen = ALIGN(dlen, dma_get_cache_alignment()); 81 struct caam_prng_ctx ctx; 82 struct device *jrdev; 83 dma_addr_t dst_dma; 84 u32 *desc; 85 u8 *buf; 86 int ret; 87 88 if (aligned_dlen < dlen) 89 return -EOVERFLOW; 90 91 buf = kzalloc(aligned_dlen, GFP_KERNEL); 92 if (!buf) 93 return -ENOMEM; 94 95 jrdev = caam_jr_alloc(); 96 ret = PTR_ERR_OR_ZERO(jrdev); 97 if (ret) { 98 pr_err("Job Ring Device allocation failed\n"); 99 kfree(buf); 100 return ret; 101 } 102 103 desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL); 104 if (!desc) { 105 ret = -ENOMEM; 106 goto out1; 107 } 108 109 dst_dma = dma_map_single(jrdev, buf, dlen, DMA_FROM_DEVICE); 110 if (dma_mapping_error(jrdev, dst_dma)) { 111 dev_err(jrdev, "Failed to map destination buffer memory\n"); 112 ret = -ENOMEM; 113 goto out; 114 } 115 116 init_completion(&ctx.done); 117 ret = caam_jr_enqueue(jrdev, 118 caam_init_prng_desc(desc, dst_dma, dlen), 119 caam_prng_done, &ctx); 120 121 if (ret == -EINPROGRESS) { 122 wait_for_completion(&ctx.done); 123 ret = ctx.err; 124 } 125 126 dma_unmap_single(jrdev, dst_dma, dlen, DMA_FROM_DEVICE); 127 128 if (!ret) 129 memcpy(dst, buf, dlen); 130 out: 131 kfree(desc); 132 out1: 133 caam_jr_free(jrdev); 134 kfree(buf); 135 return ret; 136 } 137 138 static void caam_prng_exit(struct crypto_tfm *tfm) {} 139 140 static int caam_prng_init(struct crypto_tfm *tfm) 141 { 142 return 0; 143 } 144 145 static int caam_prng_seed(struct crypto_rng *tfm, 146 const u8 *seed, unsigned int slen) 147 { 148 struct caam_prng_ctx ctx; 149 struct device *jrdev; 150 u32 *desc; 151 int ret; 152 153 if (slen) { 154 pr_err("Seed length should be zero\n"); 155 return -EINVAL; 156 } 157 158 jrdev = caam_jr_alloc(); 159 ret = PTR_ERR_OR_ZERO(jrdev); 160 if (ret) { 161 pr_err("Job Ring Device allocation failed\n"); 162 return ret; 163 } 164 165 desc = kzalloc(CAAM_PRNG_MAX_DESC_LEN, GFP_KERNEL); 166 if (!desc) { 167 caam_jr_free(jrdev); 168 return -ENOMEM; 169 } 170 171 init_completion(&ctx.done); 172 ret = caam_jr_enqueue(jrdev, 173 caam_init_reseed_desc(desc), 174 caam_prng_done, &ctx); 175 176 if (ret == -EINPROGRESS) { 177 wait_for_completion(&ctx.done); 178 ret = ctx.err; 179 } 180 181 kfree(desc); 182 caam_jr_free(jrdev); 183 return ret; 184 } 185 186 static struct caam_prng_alg caam_prng_alg = { 187 .rng = { 188 .generate = caam_prng_generate, 189 .seed = caam_prng_seed, 190 .seedsize = 0, 191 .base = { 192 .cra_name = "stdrng", 193 .cra_driver_name = "prng-caam", 194 .cra_priority = 500, 195 .cra_ctxsize = sizeof(struct caam_prng_ctx), 196 .cra_module = THIS_MODULE, 197 .cra_init = caam_prng_init, 198 .cra_exit = caam_prng_exit, 199 }, 200 } 201 }; 202 203 void caam_prng_unregister(void *data) 204 { 205 if (caam_prng_alg.registered) 206 crypto_unregister_rng(&caam_prng_alg.rng); 207 } 208 209 int caam_prng_register(struct device *ctrldev) 210 { 211 struct caam_drv_private *priv = dev_get_drvdata(ctrldev); 212 u32 rng_inst; 213 int ret = 0; 214 215 /* Check for available RNG blocks before registration */ 216 if (priv->era < 10) 217 rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) & 218 CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; 219 else 220 rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK; 221 222 if (!rng_inst) { 223 dev_dbg(ctrldev, "RNG block is not available... skipping registering algorithm\n"); 224 return ret; 225 } 226 227 ret = crypto_register_rng(&caam_prng_alg.rng); 228 if (ret) { 229 dev_err(ctrldev, 230 "couldn't register rng crypto alg: %d\n", 231 ret); 232 return ret; 233 } 234 235 caam_prng_alg.registered = true; 236 237 dev_info(ctrldev, 238 "rng crypto API alg registered %s\n", caam_prng_alg.rng.base.cra_driver_name); 239 240 return 0; 241 } 242