xref: /rk3399_rockchip-uboot/drivers/crypto/crypto-uclass.c (revision f400b2a415b8b81efcacb746ee652112601dba96)
1cc6ac5d6SJoseph Chen // SPDX-License-Identifier: GPL-2.0
2cc6ac5d6SJoseph Chen /*
3cc6ac5d6SJoseph Chen  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4cc6ac5d6SJoseph Chen  */
5cc6ac5d6SJoseph Chen 
6cc6ac5d6SJoseph Chen #include <crypto.h>
7*f400b2a4SLin Jinhan #include <keylad.h>
8cc6ac5d6SJoseph Chen 
96b5b88bcSLin Jinhan static const u8 null_hash_sha1_value[] = {
106b5b88bcSLin Jinhan 	0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
116b5b88bcSLin Jinhan 	0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
126b5b88bcSLin Jinhan 	0xaf, 0xd8, 0x07, 0x09
136b5b88bcSLin Jinhan };
146b5b88bcSLin Jinhan 
156b5b88bcSLin Jinhan static const u8 null_hash_md5_value[] = {
166b5b88bcSLin Jinhan 	0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
176b5b88bcSLin Jinhan 	0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
186b5b88bcSLin Jinhan };
196b5b88bcSLin Jinhan 
206b5b88bcSLin Jinhan static const u8 null_hash_sha256_value[] = {
216b5b88bcSLin Jinhan 	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
226b5b88bcSLin Jinhan 	0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
236b5b88bcSLin Jinhan 	0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
246b5b88bcSLin Jinhan 	0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
256b5b88bcSLin Jinhan };
266b5b88bcSLin Jinhan 
276b5b88bcSLin Jinhan static const u8 null_hash_sha512_value[] = {
286b5b88bcSLin Jinhan 	0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
296b5b88bcSLin Jinhan 	0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
306b5b88bcSLin Jinhan 	0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
316b5b88bcSLin Jinhan 	0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
326b5b88bcSLin Jinhan 	0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
336b5b88bcSLin Jinhan 	0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
346b5b88bcSLin Jinhan 	0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
356b5b88bcSLin Jinhan 	0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
366b5b88bcSLin Jinhan };
376b5b88bcSLin Jinhan 
3849a2135eSLin Jinhan const static u8 null_hash_sm3_value[] = {
3949a2135eSLin Jinhan 	0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f,
4049a2135eSLin Jinhan 	0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f,
4149a2135eSLin Jinhan 	0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74,
4249a2135eSLin Jinhan 	0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b
4349a2135eSLin Jinhan };
4449a2135eSLin Jinhan 
45cc6ac5d6SJoseph Chen u32 crypto_algo_nbits(u32 algo)
46cc6ac5d6SJoseph Chen {
47cc6ac5d6SJoseph Chen 	switch (algo) {
48cc6ac5d6SJoseph Chen 	case CRYPTO_MD5:
4949a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
50cc6ac5d6SJoseph Chen 		return 128;
51cc6ac5d6SJoseph Chen 	case CRYPTO_SHA1:
5249a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
53cc6ac5d6SJoseph Chen 		return 160;
54cc6ac5d6SJoseph Chen 	case CRYPTO_SHA256:
5549a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
56cc6ac5d6SJoseph Chen 		return 256;
57e7846385SLin Jinhan 	case CRYPTO_SHA512:
5849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
59e7846385SLin Jinhan 		return 512;
6049a2135eSLin Jinhan 	case CRYPTO_SM3:
6149a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
6249a2135eSLin Jinhan 		return 256;
63cc6ac5d6SJoseph Chen 	case CRYPTO_RSA512:
64cc6ac5d6SJoseph Chen 		return 512;
65cc6ac5d6SJoseph Chen 	case CRYPTO_RSA1024:
66cc6ac5d6SJoseph Chen 		return 1024;
67cc6ac5d6SJoseph Chen 	case CRYPTO_RSA2048:
68cc6ac5d6SJoseph Chen 		return 2048;
69b353a43cSLin Jinhan 	case CRYPTO_RSA3072:
70b353a43cSLin Jinhan 		return 3072;
71b353a43cSLin Jinhan 	case CRYPTO_RSA4096:
72b353a43cSLin Jinhan 		return 4096;
7302b4cf42SLin Jinhan 	case CRYPTO_SM2:
7402b4cf42SLin Jinhan 		return 256;
7502b4cf42SLin Jinhan 	case CRYPTO_ECC_192R1:
7602b4cf42SLin Jinhan 		return 192;
7702b4cf42SLin Jinhan 	case CRYPTO_ECC_224R1:
7802b4cf42SLin Jinhan 		return 224;
7902b4cf42SLin Jinhan 	case CRYPTO_ECC_256R1:
8002b4cf42SLin Jinhan 		return 256;
81cc6ac5d6SJoseph Chen 	}
82cc6ac5d6SJoseph Chen 
83cc6ac5d6SJoseph Chen 	printf("Unknown crypto algorithm: 0x%x\n", algo);
84cc6ac5d6SJoseph Chen 
85cc6ac5d6SJoseph Chen 	return 0;
86cc6ac5d6SJoseph Chen }
87cc6ac5d6SJoseph Chen 
88cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability)
89cc6ac5d6SJoseph Chen {
90cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops;
91cc6ac5d6SJoseph Chen 	struct udevice *dev;
92cc6ac5d6SJoseph Chen 	struct uclass *uc;
93cc6ac5d6SJoseph Chen 	int ret;
94cc6ac5d6SJoseph Chen 	u32 cap;
95cc6ac5d6SJoseph Chen 
96cc6ac5d6SJoseph Chen 	ret = uclass_get(UCLASS_CRYPTO, &uc);
97cc6ac5d6SJoseph Chen 	if (ret)
98cc6ac5d6SJoseph Chen 		return NULL;
99cc6ac5d6SJoseph Chen 
100cc6ac5d6SJoseph Chen 	for (uclass_first_device(UCLASS_CRYPTO, &dev);
101cc6ac5d6SJoseph Chen 	     dev;
102cc6ac5d6SJoseph Chen 	     uclass_next_device(&dev)) {
103cc6ac5d6SJoseph Chen 		ops = device_get_ops(dev);
104cc6ac5d6SJoseph Chen 		if (!ops || !ops->capability)
105cc6ac5d6SJoseph Chen 			continue;
106cc6ac5d6SJoseph Chen 
107cc6ac5d6SJoseph Chen 		cap = ops->capability(dev);
108cc6ac5d6SJoseph Chen 		if ((cap & capability) == capability)
109cc6ac5d6SJoseph Chen 			return dev;
110cc6ac5d6SJoseph Chen 	}
111cc6ac5d6SJoseph Chen 
112cc6ac5d6SJoseph Chen 	return NULL;
113cc6ac5d6SJoseph Chen }
114cc6ac5d6SJoseph Chen 
115cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx)
116cc6ac5d6SJoseph Chen {
117cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
118cc6ac5d6SJoseph Chen 
1196b5b88bcSLin Jinhan 	if (ctx && !ctx->length)
1206b5b88bcSLin Jinhan 		return 0;
1216b5b88bcSLin Jinhan 
122cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_init)
123cc6ac5d6SJoseph Chen 		return -ENOSYS;
124cc6ac5d6SJoseph Chen 
125cc6ac5d6SJoseph Chen 	return ops->sha_init(dev, ctx);
126cc6ac5d6SJoseph Chen }
127cc6ac5d6SJoseph Chen 
128cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
129cc6ac5d6SJoseph Chen {
130cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
131cc6ac5d6SJoseph Chen 
1326b5b88bcSLin Jinhan 	if (!len)
1336b5b88bcSLin Jinhan 		return 0;
1346b5b88bcSLin Jinhan 
135cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_update)
136cc6ac5d6SJoseph Chen 		return -ENOSYS;
137cc6ac5d6SJoseph Chen 
138cc6ac5d6SJoseph Chen 	return ops->sha_update(dev, input, len);
139cc6ac5d6SJoseph Chen }
140cc6ac5d6SJoseph Chen 
141cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
142cc6ac5d6SJoseph Chen {
143cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
1446b5b88bcSLin Jinhan 	const u8 *null_hash = NULL;
1456b5b88bcSLin Jinhan 	u32 hash_size = 0;
1466b5b88bcSLin Jinhan 
1476b5b88bcSLin Jinhan 	if (ctx && !ctx->length && output) {
1486b5b88bcSLin Jinhan 		switch (ctx->algo) {
1496b5b88bcSLin Jinhan 		case CRYPTO_MD5:
1506b5b88bcSLin Jinhan 			null_hash = null_hash_md5_value;
1516b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_md5_value);
1526b5b88bcSLin Jinhan 			break;
1536b5b88bcSLin Jinhan 		case CRYPTO_SHA1:
1546b5b88bcSLin Jinhan 			null_hash = null_hash_sha1_value;
1556b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha1_value);
1566b5b88bcSLin Jinhan 			break;
1576b5b88bcSLin Jinhan 		case CRYPTO_SHA256:
1586b5b88bcSLin Jinhan 			null_hash = null_hash_sha256_value;
1596b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha256_value);
1606b5b88bcSLin Jinhan 			break;
1616b5b88bcSLin Jinhan 		case CRYPTO_SHA512:
1626b5b88bcSLin Jinhan 			null_hash = null_hash_sha512_value;
1636b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha512_value);
1646b5b88bcSLin Jinhan 			break;
16549a2135eSLin Jinhan 		case CRYPTO_SM3:
16649a2135eSLin Jinhan 			null_hash = null_hash_sm3_value;
16749a2135eSLin Jinhan 			hash_size = sizeof(null_hash_sm3_value);
16849a2135eSLin Jinhan 			break;
1696b5b88bcSLin Jinhan 		default:
1706b5b88bcSLin Jinhan 			return -EINVAL;
1716b5b88bcSLin Jinhan 		}
1726b5b88bcSLin Jinhan 
1736b5b88bcSLin Jinhan 		memcpy(output, null_hash, hash_size);
1746b5b88bcSLin Jinhan 
1756b5b88bcSLin Jinhan 		return 0;
1766b5b88bcSLin Jinhan 	}
177cc6ac5d6SJoseph Chen 
178cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_final)
179cc6ac5d6SJoseph Chen 		return -ENOSYS;
180cc6ac5d6SJoseph Chen 
181cc6ac5d6SJoseph Chen 	return ops->sha_final(dev, ctx, output);
182cc6ac5d6SJoseph Chen }
183cc6ac5d6SJoseph Chen 
18449a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx,
18549a2135eSLin Jinhan 		     u8 *key, u32 key_len)
18649a2135eSLin Jinhan {
18749a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
18849a2135eSLin Jinhan 
18949a2135eSLin Jinhan 	if (ctx && !ctx->length)
19049a2135eSLin Jinhan 		return -EINVAL;
19149a2135eSLin Jinhan 
19249a2135eSLin Jinhan 	if (!ops || !ops->hmac_init)
19349a2135eSLin Jinhan 		return -ENOSYS;
19449a2135eSLin Jinhan 
19549a2135eSLin Jinhan 	return ops->hmac_init(dev, ctx, key, key_len);
19649a2135eSLin Jinhan }
19749a2135eSLin Jinhan 
19849a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len)
19949a2135eSLin Jinhan {
20049a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
20149a2135eSLin Jinhan 
20249a2135eSLin Jinhan 	if (!len)
20349a2135eSLin Jinhan 		return 0;
20449a2135eSLin Jinhan 
20549a2135eSLin Jinhan 	if (!ops || !ops->hmac_update)
20649a2135eSLin Jinhan 		return -ENOSYS;
20749a2135eSLin Jinhan 
20849a2135eSLin Jinhan 	return ops->hmac_update(dev, input, len);
20949a2135eSLin Jinhan }
21049a2135eSLin Jinhan 
21149a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output)
21249a2135eSLin Jinhan {
21349a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
21449a2135eSLin Jinhan 
21549a2135eSLin Jinhan 	if (!ops || !ops->hmac_final)
21649a2135eSLin Jinhan 		return -ENOSYS;
21749a2135eSLin Jinhan 
21849a2135eSLin Jinhan 	return ops->hmac_final(dev, ctx, output);
21949a2135eSLin Jinhan }
22049a2135eSLin Jinhan 
221cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx,
222cc6ac5d6SJoseph Chen 		    char *input, u32 input_len, u8 *output)
223cc6ac5d6SJoseph Chen {
224cc6ac5d6SJoseph Chen 	int ret;
225cc6ac5d6SJoseph Chen 
226cc6ac5d6SJoseph Chen 	ret = crypto_sha_init(dev, ctx);
227cc6ac5d6SJoseph Chen 	if (ret)
228cc6ac5d6SJoseph Chen 		return ret;
229cc6ac5d6SJoseph Chen 
230cc6ac5d6SJoseph Chen 	ret = crypto_sha_update(dev, (u32 *)input, input_len);
231cc6ac5d6SJoseph Chen 	if (ret)
232cc6ac5d6SJoseph Chen 		return ret;
233cc6ac5d6SJoseph Chen 
234cc6ac5d6SJoseph Chen 	ret = crypto_sha_final(dev, ctx, output);
235cc6ac5d6SJoseph Chen 
236cc6ac5d6SJoseph Chen 	return ret;
237cc6ac5d6SJoseph Chen }
238cc6ac5d6SJoseph Chen 
239c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx,
240c14e46abSJoseph Chen 			    const struct image_region region[],
241c14e46abSJoseph Chen 			    int region_count, u8 *output)
242c14e46abSJoseph Chen {
243c14e46abSJoseph Chen 	int i, ret;
244c14e46abSJoseph Chen 
245c14e46abSJoseph Chen 	ctx->length = 0;
246c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++)
247c14e46abSJoseph Chen 		ctx->length += region[i].size;
248c14e46abSJoseph Chen 
249c14e46abSJoseph Chen 	ret = crypto_sha_init(dev, ctx);
250c14e46abSJoseph Chen 	if (ret)
251c14e46abSJoseph Chen 		return ret;
252c14e46abSJoseph Chen 
253c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++) {
254c14e46abSJoseph Chen 		ret = crypto_sha_update(dev, (void *)region[i].data,
255c14e46abSJoseph Chen 					region[i].size);
256c14e46abSJoseph Chen 		if (ret)
257c14e46abSJoseph Chen 			return ret;
258c14e46abSJoseph Chen 	}
259c14e46abSJoseph Chen 
260c14e46abSJoseph Chen 	return crypto_sha_final(dev, ctx, output);
261c14e46abSJoseph Chen }
262c14e46abSJoseph Chen 
263cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output)
264cc6ac5d6SJoseph Chen {
265cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
266cc6ac5d6SJoseph Chen 
267cc6ac5d6SJoseph Chen 	if (!ops || !ops->rsa_verify)
268cc6ac5d6SJoseph Chen 		return -ENOSYS;
269cc6ac5d6SJoseph Chen 
270549a74f7SLin Jinhan 	if (!ctx || !ctx->n || !ctx->e || !sign || !output)
271549a74f7SLin Jinhan 		return -EINVAL;
272549a74f7SLin Jinhan 
273cc6ac5d6SJoseph Chen 	return ops->rsa_verify(dev, ctx, sign, output);
274cc6ac5d6SJoseph Chen }
275cc6ac5d6SJoseph Chen 
27602b4cf42SLin Jinhan int crypto_ec_verify(struct udevice *dev, ec_key *ctx, u8 *hash, u32 hash_len, u8 *sign)
27702b4cf42SLin Jinhan {
27802b4cf42SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
27902b4cf42SLin Jinhan 
28002b4cf42SLin Jinhan 	if (!ops || !ops->ec_verify)
28102b4cf42SLin Jinhan 		return -ENOSYS;
28202b4cf42SLin Jinhan 
28302b4cf42SLin Jinhan 	if (!ctx || !ctx->x || !ctx->y || !ctx->y || !hash || hash_len == 0 || !sign)
28402b4cf42SLin Jinhan 		return -EINVAL;
28502b4cf42SLin Jinhan 
28602b4cf42SLin Jinhan 	return ops->ec_verify(dev, ctx, hash, hash_len, sign);
28702b4cf42SLin Jinhan }
28802b4cf42SLin Jinhan 
28949a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx,
29049a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
29149a2135eSLin Jinhan {
29249a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
29349a2135eSLin Jinhan 
29449a2135eSLin Jinhan 	if (!ops || !ops->cipher_crypt)
29549a2135eSLin Jinhan 		return -ENOSYS;
29649a2135eSLin Jinhan 
297*f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
298*f400b2a4SLin Jinhan 		return -EINVAL;
299*f400b2a4SLin Jinhan 
30049a2135eSLin Jinhan 	return ops->cipher_crypt(dev, ctx, in, out, len, enc);
30149a2135eSLin Jinhan }
30249a2135eSLin Jinhan 
303d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx,
304d9332f1cSLin Jinhan 	       const u8 *in, u32 len, u8 *tag)
305d9332f1cSLin Jinhan {
306d9332f1cSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
307d9332f1cSLin Jinhan 
308d9332f1cSLin Jinhan 	if (!ops || !ops->cipher_mac)
309d9332f1cSLin Jinhan 		return -ENOSYS;
310d9332f1cSLin Jinhan 
311*f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
312*f400b2a4SLin Jinhan 		return -EINVAL;
313*f400b2a4SLin Jinhan 
314d9332f1cSLin Jinhan 	return ops->cipher_mac(dev, ctx, in, len, tag);
315d9332f1cSLin Jinhan }
316d9332f1cSLin Jinhan 
317c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx,
318c3ce9937SLin Jinhan 	      const u8 *in, u32 len, const u8 *aad, u32 aad_len,
319c3ce9937SLin Jinhan 	      u8 *out, u8 *tag)
320c3ce9937SLin Jinhan {
321c3ce9937SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
322c3ce9937SLin Jinhan 
323c3ce9937SLin Jinhan 	if (!ops || !ops->cipher_ae)
324c3ce9937SLin Jinhan 		return -ENOSYS;
325c3ce9937SLin Jinhan 
326*f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
327*f400b2a4SLin Jinhan 		return -EINVAL;
328*f400b2a4SLin Jinhan 
329c3ce9937SLin Jinhan 	return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag);
330c3ce9937SLin Jinhan }
331c3ce9937SLin Jinhan 
332*f400b2a4SLin Jinhan int crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx,
333*f400b2a4SLin Jinhan 		     const u8 *in, u8 *out, u32 len, bool enc)
334*f400b2a4SLin Jinhan {
335*f400b2a4SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
336*f400b2a4SLin Jinhan 	struct udevice *keylad_dev;
337*f400b2a4SLin Jinhan 
338*f400b2a4SLin Jinhan 	if (!ops || !ops->cipher_fw_crypt)
339*f400b2a4SLin Jinhan 		return -ENOSYS;
340*f400b2a4SLin Jinhan 
341*f400b2a4SLin Jinhan 	keylad_dev = keylad_get_device();
342*f400b2a4SLin Jinhan 	if (!keylad_dev) {
343*f400b2a4SLin Jinhan 		printf("No keylad device found.\n");
344*f400b2a4SLin Jinhan 		return -ENOSYS;
345*f400b2a4SLin Jinhan 	}
346*f400b2a4SLin Jinhan 
347*f400b2a4SLin Jinhan 	if (keylad_transfer_fwkey(keylad_dev, crypto_keytable_addr(dev),
348*f400b2a4SLin Jinhan 				  ctx->fw_keyid, ctx->key_len)) {
349*f400b2a4SLin Jinhan 		printf("Failed to transfer key from keylad.\n");
350*f400b2a4SLin Jinhan 		return -ENOSYS;
351*f400b2a4SLin Jinhan 	}
352*f400b2a4SLin Jinhan 
353*f400b2a4SLin Jinhan 	return ops->cipher_fw_crypt(dev, ctx, in, out, len, enc);
354*f400b2a4SLin Jinhan }
355*f400b2a4SLin Jinhan 
356*f400b2a4SLin Jinhan ulong crypto_keytable_addr(struct udevice *dev)
357*f400b2a4SLin Jinhan {
358*f400b2a4SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
359*f400b2a4SLin Jinhan 
360*f400b2a4SLin Jinhan 	if (!ops || !ops->keytable_addr)
361*f400b2a4SLin Jinhan 		return 0;
362*f400b2a4SLin Jinhan 
363*f400b2a4SLin Jinhan 	return ops->keytable_addr(dev);
364*f400b2a4SLin Jinhan }
365*f400b2a4SLin Jinhan 
366cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = {
367cc6ac5d6SJoseph Chen 	.id	= UCLASS_CRYPTO,
368cc6ac5d6SJoseph Chen 	.name	= "crypto",
369cc6ac5d6SJoseph Chen };
370