Home | History | Annotate | Line # | Download | only in rockchip
      1 /*	$NetBSD: rk_v1crypto.c,v 1.12 2026/01/11 07:21:46 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2020 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Taylor R. Campbell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * rk_v1crypto -- Rockchip crypto v1 driver
     34  *
     35  * This is just the RNG for now.
     36  */
     37 
     38 #include <sys/cdefs.h>
     39 __KERNEL_RCSID(1, "$NetBSD: rk_v1crypto.c,v 1.12 2026/01/11 07:21:46 skrll Exp $");
     40 
     41 #include <sys/types.h>
     42 
     43 #include <sys/bus.h>
     44 #include <sys/device.h>
     45 #include <sys/errno.h>
     46 #include <sys/mutex.h>
     47 #include <sys/rndsource.h>
     48 #include <sys/sysctl.h>
     49 
     50 #include <dev/fdt/fdtvar.h>
     51 
     52 #include <arm/rockchip/rk_v1crypto.h>
     53 
     54 struct rk_v1crypto_softc {
     55 	device_t			sc_dev;
     56 	bus_space_tag_t			sc_bst;
     57 	bus_space_handle_t		sc_bsh;
     58 	kmutex_t			sc_lock;
     59 	struct krndsource		sc_rndsource;
     60 	struct rk_v1crypto_sysctl {
     61 		struct sysctllog		*cy_log;
     62 		const struct sysctlnode		*cy_root_node;
     63 	}				sc_sysctl;
     64 };
     65 
     66 static int rk_v1crypto_match(device_t, cfdata_t, void *);
     67 static void rk_v1crypto_attach(device_t, device_t, void *);
     68 static int rk_v1crypto_selftest(struct rk_v1crypto_softc *);
     69 static void rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc *);
     70 static void rk_v1crypto_rng_get(size_t, void *);
     71 static void rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc *);
     72 static int rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS);
     73 static int rk_v1crypto_rng(struct rk_v1crypto_softc *,
     74     uint32_t[static RK_V1CRYPTO_TRNG_NOUT]);
     75 
     76 static uint32_t
     77 RKC_READ(struct rk_v1crypto_softc *sc, bus_addr_t reg)
     78 {
     79 	return bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg);
     80 }
     81 
     82 static void
     83 RKC_WRITE(struct rk_v1crypto_softc *sc, bus_addr_t reg, uint32_t v)
     84 {
     85 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, v);
     86 }
     87 
     88 static inline void
     89 RKC_CTRL(struct rk_v1crypto_softc *sc, uint16_t m, uint16_t v)
     90 {
     91 	uint32_t c = 0;
     92 
     93 	c |= __SHIFTIN(m, RK_V1CRYPTO_CTRL_MASK);
     94 	c |= __SHIFTIN(v, m);
     95 	RKC_WRITE(sc, RK_V1CRYPTO_CTRL, c);
     96 }
     97 
     98 CFATTACH_DECL_NEW(rk_v1crypto, sizeof(struct rk_v1crypto_softc),
     99     rk_v1crypto_match, rk_v1crypto_attach, NULL, NULL);
    100 
    101 struct rk_v1crypto_data {
    102 	int num_clks;
    103 	const char *const clks[];
    104 };
    105 
    106 static const struct rk_v1crypto_data rk3288_crypto_data = {
    107 	.num_clks = 4,
    108 	.clks = {"aclk", "hclk", "sclk", "apb_pclk"},
    109 };
    110 
    111 static const struct rk_v1crypto_data rk3328_crypto_data = {
    112 	.num_clks = 3,
    113 	.clks = {"hclk_master", "hclk_slave", "sclk"},
    114 };
    115 
    116 static const struct device_compatible_entry compat_data[] = {
    117 	{ .compat = "rockchip,rk3288-crypto", .data = &rk3288_crypto_data },
    118 	{ .compat = "rockchip,rk3328-crypto", .data = &rk3328_crypto_data },
    119 	{ .compat = "rockchip,rk3399-crypto", .data = &rk3328_crypto_data },
    120 	DEVICE_COMPAT_EOL
    121 };
    122 
    123 static int
    124 rk_v1crypto_match(device_t parent, cfdata_t cf, void *aux)
    125 {
    126 	const struct fdt_attach_args *const faa = aux;
    127 
    128 	return of_compatible_match(faa->faa_phandle, compat_data);
    129 }
    130 
    131 static void
    132 rk_v1crypto_attach(device_t parent, device_t self, void *aux)
    133 {
    134 	struct rk_v1crypto_softc *const sc = device_private(self);
    135 	const struct fdt_attach_args *const faa = aux;
    136 	bus_addr_t addr;
    137 	bus_size_t size;
    138 	const int phandle = faa->faa_phandle;
    139 	struct fdtbus_reset *rst;
    140 	unsigned i;
    141 	uint32_t ctrl;
    142 	const struct rk_v1crypto_data *config =
    143 	    of_compatible_lookup(phandle, compat_data)->data;
    144 	const char *const *clks = config->clks;
    145 
    146 	fdtbus_clock_assign(phandle);
    147 
    148 	sc->sc_dev = self;
    149 	sc->sc_bst = faa->faa_bst;
    150 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
    151 
    152 	/* Get and map device registers.  */
    153 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
    154 		aprint_error(": couldn't get registers\n");
    155 		return;
    156 	}
    157 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
    158 		aprint_error(": couldn't map registers\n");
    159 		return;
    160 	}
    161 
    162 	/* Enable the clocks.  */
    163 	for (i = 0; i < config->num_clks; i++) {
    164 		if (fdtbus_clock_enable(phandle, clks[i], true) != 0) {
    165 			aprint_error(": couldn't enable %s clock\n", clks[i]);
    166 			return;
    167 		}
    168 	}
    169 
    170 	/* Get a reset handle if we need and try to deassert it.  */
    171 	if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL) {
    172 		if (fdtbus_reset_deassert(rst) != 0) {
    173 			aprint_error(": couldn't de-assert reset\n");
    174 			return;
    175 		}
    176 	}
    177 
    178 	aprint_naive("\n");
    179 	aprint_normal(": Crypto v1\n");
    180 
    181 	/*
    182 	 * Enable ring oscillator to start gathering entropy, and set
    183 	 * up the crypto clock to sample it once every 100 cycles.
    184 	 *
    185 	 * The ring oscillator can run even when the clock is gated or
    186 	 * flush is asserted, and the longer we run it, the less it
    187 	 * will be synchronized with the main clock owing to jitter
    188 	 * ideally from unpredictable thermal noise.
    189 	 */
    190 	ctrl = RK_V1CRYPTO_TRNG_CTRL_OSC_ENABLE;
    191 	ctrl |= __SHIFTIN(100, RK_V1CRYPTO_TRNG_CTRL_CYCLES);
    192 	RKC_WRITE(sc, RK_V1CRYPTO_TRNG_CTRL, ctrl);
    193 
    194 	if (rk_v1crypto_selftest(sc))
    195 		return;
    196 	rk_v1crypto_rndsource_attach(sc);
    197 	rk_v1crypto_sysctl_attach(sc);
    198 }
    199 
    200 static int
    201 rk_v1crypto_selftest(struct rk_v1crypto_softc *sc)
    202 {
    203 	static const uint32_t key[4] = {0};
    204 	static const uint32_t input[4] = {0};
    205 	static const uint32_t expected[4] = {
    206 		0x66e94bd4, 0xef8a2c3b, 0x884cfa59, 0xca342b2e,
    207 	};
    208 	uint32_t output[4];
    209 	uint32_t ctrl;
    210 	unsigned i, timo;
    211 
    212 	/* Program the key and input block.  */
    213 	for (i = 0; i < 4; i++)
    214 		RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), key[i]);
    215 	for (i = 0; i < 4; i++)
    216 		RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), input[i]);
    217 
    218 	/*
    219 	 * Set up the AES unit to do AES-128 `ECB' (i.e., just the raw
    220 	 * AES permutation) in the encryption direction.
    221 	 */
    222 	ctrl = 0;
    223 	ctrl |= RK_V1CRYPTO_AES_CTRL_KEYCHANGE;
    224 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_MODE_ECB,
    225 	    RK_V1CRYPTO_AES_CTRL_MODE);
    226 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_KEYSIZE_128,
    227 	    RK_V1CRYPTO_AES_CTRL_KEYSIZE);
    228 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_DIR_ENC,
    229 	    RK_V1CRYPTO_AES_CTRL_DIR);
    230 	RKC_WRITE(sc, RK_V1CRYPTO_AES_CTRL, ctrl);
    231 
    232 	/* Kick it off.  */
    233 	RKC_CTRL(sc, RK_V1CRYPTO_CTRL_AES_START, 1);
    234 
    235 	/* Wait up to 1ms for it to complete.  */
    236 	timo = 1000;
    237 	while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_AES_START) {
    238 		if (--timo == 0) {
    239 			device_printf(sc->sc_dev, "AES self-test timed out\n");
    240 			return -1;
    241 		}
    242 		DELAY(1);
    243 	}
    244 
    245 	/* Read the output.  */
    246 	for (i = 0; i < 4; i++)
    247 		output[i] = RKC_READ(sc, RK_V1CRYPTO_AES_DOUT(i));
    248 
    249 	/* Verify the output.  */
    250 	for (i = 0; i < 4; i++) {
    251 		if (output[i] != expected[i]) {
    252 			device_printf(sc->sc_dev, "AES self-test failed\n");
    253 			return -1;
    254 		}
    255 	}
    256 
    257 	/* Success!  */
    258 	return 0;
    259 }
    260 
    261 static void
    262 rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc *sc)
    263 {
    264 	device_t self = sc->sc_dev;
    265 
    266 	rndsource_setcb(&sc->sc_rndsource, rk_v1crypto_rng_get, sc);
    267 	rnd_attach_source(&sc->sc_rndsource, device_xname(self),
    268 	    RND_TYPE_RNG, RND_FLAG_DEFAULT|RND_FLAG_HASCB);
    269 }
    270 
    271 static void
    272 rk_v1crypto_rng_get(size_t nbytes, void *cookie)
    273 {
    274 	struct rk_v1crypto_softc *sc = cookie;
    275 	device_t self = sc->sc_dev;
    276 	uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
    277 	uint32_t entropybits = NBBY*sizeof(buf)/2; /* be conservative */
    278 	unsigned n = RK_V1CRYPTO_TRNG_NOUT;
    279 	int error;
    280 	size_t nbits = NBBY*nbytes;
    281 
    282 	while (nbits) {
    283 		CTASSERT((RK_V1CRYPTO_TRNG_NOUT % 2) == 0);
    284 
    285 		error = rk_v1crypto_rng(sc, buf);
    286 		if (error) {
    287 			device_printf(self, "timed out\n");
    288 			break;
    289 		}
    290 		if (consttime_memequal(buf, buf + n/2, sizeof(buf[0]) * n/2)) {
    291 			device_printf(self, "failed repeated output test\n");
    292 			break;
    293 		}
    294 		rnd_add_data_sync(&sc->sc_rndsource, buf, sizeof buf,
    295 		    entropybits);
    296 		nbits -= MIN(nbits, MAX(1, entropybits));
    297 	}
    298 	explicit_memset(buf, 0, sizeof buf);
    299 }
    300 
    301 static void
    302 rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc *sc)
    303 {
    304 	device_t self = sc->sc_dev;
    305 	struct rk_v1crypto_sysctl *cy = &sc->sc_sysctl;
    306 	int error;
    307 
    308 	/* hw.rkv1cryptoN (node) */
    309 	error = sysctl_createv(&cy->cy_log, 0, NULL, &cy->cy_root_node,
    310 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(self),
    311 	    SYSCTL_DESCR("rk crypto v1 engine knobs"),
    312 	    NULL, 0, NULL, 0,
    313 	    CTL_HW, CTL_CREATE, CTL_EOL);
    314 	if (error) {
    315 		aprint_error_dev(self,
    316 		    "failed to set up sysctl hw.%s: %d\n",
    317 		    device_xname(self), error);
    318 		return;
    319 	}
    320 
    321 	/* hw.rkv1cryptoN.rng (`struct', 32-byte array) */
    322 	error = sysctl_createv(&cy->cy_log, 0, &cy->cy_root_node, NULL,
    323 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT,
    324 	    "rng", SYSCTL_DESCR("Read up to 32 bytes out of the TRNG"),
    325 	    &rk_v1crypto_sysctl_rng, 0, sc, 0, CTL_CREATE, CTL_EOL);
    326 	if (error) {
    327 		aprint_error_dev(self,
    328 		    "failed to set up sysctl hw.%s.rng: %d\n",
    329 		    device_xname(self), error);
    330 		return;
    331 	}
    332 }
    333 
    334 static int
    335 rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS)
    336 {
    337 	uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
    338 	struct sysctlnode node = *rnode;
    339 	struct rk_v1crypto_softc *sc = node.sysctl_data;
    340 	size_t size;
    341 	int error;
    342 
    343 	/* If oldp == NULL, the caller wants to learn the size.  */
    344 	if (oldp == NULL) {
    345 		*oldlenp = sizeof buf;
    346 		return 0;
    347 	}
    348 
    349 	/* Verify the output buffer size is reasonable.  */
    350 	size = *oldlenp;
    351 	if (size > sizeof buf)	/* size_t, so never negative */
    352 		return E2BIG;
    353 	if (size == 0)
    354 		return 0;	/* nothing to do */
    355 
    356 	/* Generate data.  */
    357 	error = rk_v1crypto_rng(sc, buf);
    358 	if (error)
    359 		return error;
    360 
    361 	/* Copy out the data.  */
    362 	node.sysctl_data = buf;
    363 	node.sysctl_size = size;
    364 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    365 
    366 	/* Clear the buffer.  */
    367 	explicit_memset(buf, 0, sizeof buf);
    368 
    369 	/* Return the sysctl_lookup error, if any.  */
    370 	return error;
    371 }
    372 
    373 static int
    374 rk_v1crypto_rng(struct rk_v1crypto_softc *sc,
    375     uint32_t buf[static RK_V1CRYPTO_TRNG_NOUT])
    376 {
    377 	unsigned i, timo;
    378 	int error;
    379 
    380 	/* Acquire lock to serialize access to TRNG.  */
    381 	mutex_enter(&sc->sc_lock);
    382 
    383 	/*
    384 	 * Query TRNG and wait up to 1ms for it to post.  Empirically,
    385 	 * this takes around 120us.
    386 	 */
    387 	RKC_CTRL(sc, RK_V1CRYPTO_CTRL_TRNG_START, 1);
    388 	timo = 1000;
    389 	while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_TRNG_START) {
    390 		if (--timo == 0) {
    391 			error = ETIMEDOUT;
    392 			goto out;
    393 		}
    394 		DELAY(1);
    395 	}
    396 
    397 	/* Read out the data.  */
    398 	for (i = 0; i < RK_V1CRYPTO_TRNG_NOUT; i++)
    399 		buf[i] = RKC_READ(sc, RK_V1CRYPTO_TRNG_DOUT(i));
    400 
    401 	/* Success!  */
    402 	error = 0;
    403 out:	mutex_exit(&sc->sc_lock);
    404 	return error;
    405 }
    406