xref: /rk3399_rockchip-uboot/drivers/crypto/crypto-uclass.c (revision 24a57c1cd2f134900b2e0f34de0719cbbd2491ee)
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>
7f400b2a4SLin 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 
crypto_algo_nbits(u32 algo)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 
crypto_get_device(u32 capability)88cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability)
89cc6ac5d6SJoseph Chen {
9036e17db4Stroy.lin 	bool preferred_secure = false;
9136e17db4Stroy.lin 	bool cur_secure = false;
92cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops;
9336e17db4Stroy.lin 	struct udevice *best_fit_dev = NULL;
94cc6ac5d6SJoseph Chen 	struct udevice *dev;
95cc6ac5d6SJoseph Chen 	struct uclass *uc;
96cc6ac5d6SJoseph Chen 	int ret;
97cc6ac5d6SJoseph Chen 	u32 cap;
98cc6ac5d6SJoseph Chen 
9936e17db4Stroy.lin #if defined(CONFIG_SPL_BUILD)
10036e17db4Stroy.lin 	preferred_secure = true;
10136e17db4Stroy.lin #else
10236e17db4Stroy.lin 	preferred_secure = false;
10336e17db4Stroy.lin #endif
10436e17db4Stroy.lin 
105cc6ac5d6SJoseph Chen 	ret = uclass_get(UCLASS_CRYPTO, &uc);
106cc6ac5d6SJoseph Chen 	if (ret)
107cc6ac5d6SJoseph Chen 		return NULL;
108cc6ac5d6SJoseph Chen 
109cc6ac5d6SJoseph Chen 	for (uclass_first_device(UCLASS_CRYPTO, &dev);
110cc6ac5d6SJoseph Chen 	     dev;
111cc6ac5d6SJoseph Chen 	     uclass_next_device(&dev)) {
112cc6ac5d6SJoseph Chen 		ops = device_get_ops(dev);
113cc6ac5d6SJoseph Chen 		if (!ops || !ops->capability)
114cc6ac5d6SJoseph Chen 			continue;
115cc6ac5d6SJoseph Chen 
11636e17db4Stroy.lin 		cur_secure = ops->is_secure ? ops->is_secure(dev) : false;
11736e17db4Stroy.lin 
118cc6ac5d6SJoseph Chen 		cap = ops->capability(dev);
11936e17db4Stroy.lin 		if ((cap & capability) == capability) {
12036e17db4Stroy.lin 			if (!best_fit_dev) {
12136e17db4Stroy.lin 				best_fit_dev = dev;
12236e17db4Stroy.lin 				continue;
123cc6ac5d6SJoseph Chen 			}
124cc6ac5d6SJoseph Chen 
12536e17db4Stroy.lin 			if (preferred_secure == cur_secure)
12636e17db4Stroy.lin 				best_fit_dev = dev;
12736e17db4Stroy.lin 		}
12836e17db4Stroy.lin 	}
12936e17db4Stroy.lin 
13036e17db4Stroy.lin 	return best_fit_dev;
131cc6ac5d6SJoseph Chen }
132cc6ac5d6SJoseph Chen 
crypto_sha_init(struct udevice * dev,sha_context * ctx)133cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx)
134cc6ac5d6SJoseph Chen {
135cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
136cc6ac5d6SJoseph Chen 
1376b5b88bcSLin Jinhan 	if (ctx && !ctx->length)
1386b5b88bcSLin Jinhan 		return 0;
1396b5b88bcSLin Jinhan 
140cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_init)
141cc6ac5d6SJoseph Chen 		return -ENOSYS;
142cc6ac5d6SJoseph Chen 
143cc6ac5d6SJoseph Chen 	return ops->sha_init(dev, ctx);
144cc6ac5d6SJoseph Chen }
145cc6ac5d6SJoseph Chen 
crypto_sha_update(struct udevice * dev,u32 * input,u32 len)146cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
147cc6ac5d6SJoseph Chen {
148cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
149cc6ac5d6SJoseph Chen 
1506b5b88bcSLin Jinhan 	if (!len)
1516b5b88bcSLin Jinhan 		return 0;
1526b5b88bcSLin Jinhan 
153cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_update)
154cc6ac5d6SJoseph Chen 		return -ENOSYS;
155cc6ac5d6SJoseph Chen 
156cc6ac5d6SJoseph Chen 	return ops->sha_update(dev, input, len);
157cc6ac5d6SJoseph Chen }
158cc6ac5d6SJoseph Chen 
crypto_sha_final(struct udevice * dev,sha_context * ctx,u8 * output)159cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
160cc6ac5d6SJoseph Chen {
161cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
1626b5b88bcSLin Jinhan 	const u8 *null_hash = NULL;
1636b5b88bcSLin Jinhan 	u32 hash_size = 0;
1646b5b88bcSLin Jinhan 
1656b5b88bcSLin Jinhan 	if (ctx && !ctx->length && output) {
1666b5b88bcSLin Jinhan 		switch (ctx->algo) {
1676b5b88bcSLin Jinhan 		case CRYPTO_MD5:
1686b5b88bcSLin Jinhan 			null_hash = null_hash_md5_value;
1696b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_md5_value);
1706b5b88bcSLin Jinhan 			break;
1716b5b88bcSLin Jinhan 		case CRYPTO_SHA1:
1726b5b88bcSLin Jinhan 			null_hash = null_hash_sha1_value;
1736b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha1_value);
1746b5b88bcSLin Jinhan 			break;
1756b5b88bcSLin Jinhan 		case CRYPTO_SHA256:
1766b5b88bcSLin Jinhan 			null_hash = null_hash_sha256_value;
1776b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha256_value);
1786b5b88bcSLin Jinhan 			break;
1796b5b88bcSLin Jinhan 		case CRYPTO_SHA512:
1806b5b88bcSLin Jinhan 			null_hash = null_hash_sha512_value;
1816b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha512_value);
1826b5b88bcSLin Jinhan 			break;
18349a2135eSLin Jinhan 		case CRYPTO_SM3:
18449a2135eSLin Jinhan 			null_hash = null_hash_sm3_value;
18549a2135eSLin Jinhan 			hash_size = sizeof(null_hash_sm3_value);
18649a2135eSLin Jinhan 			break;
1876b5b88bcSLin Jinhan 		default:
1886b5b88bcSLin Jinhan 			return -EINVAL;
1896b5b88bcSLin Jinhan 		}
1906b5b88bcSLin Jinhan 
1916b5b88bcSLin Jinhan 		memcpy(output, null_hash, hash_size);
1926b5b88bcSLin Jinhan 
1936b5b88bcSLin Jinhan 		return 0;
1946b5b88bcSLin Jinhan 	}
195cc6ac5d6SJoseph Chen 
196cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_final)
197cc6ac5d6SJoseph Chen 		return -ENOSYS;
198cc6ac5d6SJoseph Chen 
199cc6ac5d6SJoseph Chen 	return ops->sha_final(dev, ctx, output);
200cc6ac5d6SJoseph Chen }
201cc6ac5d6SJoseph Chen 
crypto_hmac_init(struct udevice * dev,sha_context * ctx,u8 * key,u32 key_len)20249a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx,
20349a2135eSLin Jinhan 		     u8 *key, u32 key_len)
20449a2135eSLin Jinhan {
20549a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
20649a2135eSLin Jinhan 
20749a2135eSLin Jinhan 	if (ctx && !ctx->length)
20849a2135eSLin Jinhan 		return -EINVAL;
20949a2135eSLin Jinhan 
21049a2135eSLin Jinhan 	if (!ops || !ops->hmac_init)
21149a2135eSLin Jinhan 		return -ENOSYS;
21249a2135eSLin Jinhan 
21349a2135eSLin Jinhan 	return ops->hmac_init(dev, ctx, key, key_len);
21449a2135eSLin Jinhan }
21549a2135eSLin Jinhan 
crypto_hmac_update(struct udevice * dev,u32 * input,u32 len)21649a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len)
21749a2135eSLin Jinhan {
21849a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
21949a2135eSLin Jinhan 
22049a2135eSLin Jinhan 	if (!len)
22149a2135eSLin Jinhan 		return 0;
22249a2135eSLin Jinhan 
22349a2135eSLin Jinhan 	if (!ops || !ops->hmac_update)
22449a2135eSLin Jinhan 		return -ENOSYS;
22549a2135eSLin Jinhan 
22649a2135eSLin Jinhan 	return ops->hmac_update(dev, input, len);
22749a2135eSLin Jinhan }
22849a2135eSLin Jinhan 
crypto_hmac_final(struct udevice * dev,sha_context * ctx,u8 * output)22949a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output)
23049a2135eSLin Jinhan {
23149a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
23249a2135eSLin Jinhan 
23349a2135eSLin Jinhan 	if (!ops || !ops->hmac_final)
23449a2135eSLin Jinhan 		return -ENOSYS;
23549a2135eSLin Jinhan 
23649a2135eSLin Jinhan 	return ops->hmac_final(dev, ctx, output);
23749a2135eSLin Jinhan }
23849a2135eSLin Jinhan 
crypto_sha_csum(struct udevice * dev,sha_context * ctx,char * input,u32 input_len,u8 * output)239cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx,
240cc6ac5d6SJoseph Chen 		    char *input, u32 input_len, u8 *output)
241cc6ac5d6SJoseph Chen {
242cc6ac5d6SJoseph Chen 	int ret;
243cc6ac5d6SJoseph Chen 
244cc6ac5d6SJoseph Chen 	ret = crypto_sha_init(dev, ctx);
245cc6ac5d6SJoseph Chen 	if (ret)
246cc6ac5d6SJoseph Chen 		return ret;
247cc6ac5d6SJoseph Chen 
248cc6ac5d6SJoseph Chen 	ret = crypto_sha_update(dev, (u32 *)input, input_len);
249cc6ac5d6SJoseph Chen 	if (ret)
250cc6ac5d6SJoseph Chen 		return ret;
251cc6ac5d6SJoseph Chen 
252cc6ac5d6SJoseph Chen 	ret = crypto_sha_final(dev, ctx, output);
253cc6ac5d6SJoseph Chen 
254cc6ac5d6SJoseph Chen 	return ret;
255cc6ac5d6SJoseph Chen }
256cc6ac5d6SJoseph Chen 
crypto_sha_regions_csum(struct udevice * dev,sha_context * ctx,const struct image_region region[],int region_count,u8 * output)257c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx,
258c14e46abSJoseph Chen 			    const struct image_region region[],
259c14e46abSJoseph Chen 			    int region_count, u8 *output)
260c14e46abSJoseph Chen {
261c14e46abSJoseph Chen 	int i, ret;
262c14e46abSJoseph Chen 
263c14e46abSJoseph Chen 	ctx->length = 0;
264c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++)
265c14e46abSJoseph Chen 		ctx->length += region[i].size;
266c14e46abSJoseph Chen 
267c14e46abSJoseph Chen 	ret = crypto_sha_init(dev, ctx);
268c14e46abSJoseph Chen 	if (ret)
269c14e46abSJoseph Chen 		return ret;
270c14e46abSJoseph Chen 
271c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++) {
272c14e46abSJoseph Chen 		ret = crypto_sha_update(dev, (void *)region[i].data,
273c14e46abSJoseph Chen 					region[i].size);
274c14e46abSJoseph Chen 		if (ret)
275c14e46abSJoseph Chen 			return ret;
276c14e46abSJoseph Chen 	}
277c14e46abSJoseph Chen 
278c14e46abSJoseph Chen 	return crypto_sha_final(dev, ctx, output);
279c14e46abSJoseph Chen }
280c14e46abSJoseph Chen 
crypto_rsa_verify(struct udevice * dev,rsa_key * ctx,u8 * sign,u8 * output)281cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output)
282cc6ac5d6SJoseph Chen {
283cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
284cc6ac5d6SJoseph Chen 
285cc6ac5d6SJoseph Chen 	if (!ops || !ops->rsa_verify)
286cc6ac5d6SJoseph Chen 		return -ENOSYS;
287cc6ac5d6SJoseph Chen 
288549a74f7SLin Jinhan 	if (!ctx || !ctx->n || !ctx->e || !sign || !output)
289549a74f7SLin Jinhan 		return -EINVAL;
290549a74f7SLin Jinhan 
291cc6ac5d6SJoseph Chen 	return ops->rsa_verify(dev, ctx, sign, output);
292cc6ac5d6SJoseph Chen }
293cc6ac5d6SJoseph Chen 
crypto_ec_verify(struct udevice * dev,ec_key * ctx,u8 * hash,u32 hash_len,u8 * sign)29402b4cf42SLin Jinhan int crypto_ec_verify(struct udevice *dev, ec_key *ctx, u8 *hash, u32 hash_len, u8 *sign)
29502b4cf42SLin Jinhan {
29602b4cf42SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
29702b4cf42SLin Jinhan 
29802b4cf42SLin Jinhan 	if (!ops || !ops->ec_verify)
29902b4cf42SLin Jinhan 		return -ENOSYS;
30002b4cf42SLin Jinhan 
30102b4cf42SLin Jinhan 	if (!ctx || !ctx->x || !ctx->y || !ctx->y || !hash || hash_len == 0 || !sign)
30202b4cf42SLin Jinhan 		return -EINVAL;
30302b4cf42SLin Jinhan 
30402b4cf42SLin Jinhan 	return ops->ec_verify(dev, ctx, hash, hash_len, sign);
30502b4cf42SLin Jinhan }
30602b4cf42SLin Jinhan 
crypto_cipher(struct udevice * dev,cipher_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)30749a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx,
30849a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
30949a2135eSLin Jinhan {
31049a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
31149a2135eSLin Jinhan 
31249a2135eSLin Jinhan 	if (!ops || !ops->cipher_crypt)
31349a2135eSLin Jinhan 		return -ENOSYS;
31449a2135eSLin Jinhan 
315f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
316f400b2a4SLin Jinhan 		return -EINVAL;
317f400b2a4SLin Jinhan 
31849a2135eSLin Jinhan 	return ops->cipher_crypt(dev, ctx, in, out, len, enc);
31949a2135eSLin Jinhan }
32049a2135eSLin Jinhan 
crypto_mac(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,u8 * tag)321d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx,
322d9332f1cSLin Jinhan 	       const u8 *in, u32 len, u8 *tag)
323d9332f1cSLin Jinhan {
324d9332f1cSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
325d9332f1cSLin Jinhan 
326d9332f1cSLin Jinhan 	if (!ops || !ops->cipher_mac)
327d9332f1cSLin Jinhan 		return -ENOSYS;
328d9332f1cSLin Jinhan 
329f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
330f400b2a4SLin Jinhan 		return -EINVAL;
331f400b2a4SLin Jinhan 
332d9332f1cSLin Jinhan 	return ops->cipher_mac(dev, ctx, in, len, tag);
333d9332f1cSLin Jinhan }
334d9332f1cSLin Jinhan 
crypto_ae(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,const u8 * aad,u32 aad_len,u8 * out,u8 * tag)335c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx,
336c3ce9937SLin Jinhan 	      const u8 *in, u32 len, const u8 *aad, u32 aad_len,
337c3ce9937SLin Jinhan 	      u8 *out, u8 *tag)
338c3ce9937SLin Jinhan {
339c3ce9937SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
340c3ce9937SLin Jinhan 
341c3ce9937SLin Jinhan 	if (!ops || !ops->cipher_ae)
342c3ce9937SLin Jinhan 		return -ENOSYS;
343c3ce9937SLin Jinhan 
344f400b2a4SLin Jinhan 	if (!ctx || !ctx->key || ctx->key_len == 0)
345f400b2a4SLin Jinhan 		return -EINVAL;
346f400b2a4SLin Jinhan 
347c3ce9937SLin Jinhan 	return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag);
348c3ce9937SLin Jinhan }
349c3ce9937SLin Jinhan 
crypto_fw_cipher(struct udevice * dev,cipher_fw_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)350f400b2a4SLin Jinhan int crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx,
351f400b2a4SLin Jinhan 		     const u8 *in, u8 *out, u32 len, bool enc)
352f400b2a4SLin Jinhan {
353*24a57c1cSLin Jinhan #if CONFIG_IS_ENABLED(DM_KEYLAD)
354f400b2a4SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
355f400b2a4SLin Jinhan 	struct udevice *keylad_dev;
356f400b2a4SLin Jinhan 
357f400b2a4SLin Jinhan 	if (!ops || !ops->cipher_fw_crypt)
358f400b2a4SLin Jinhan 		return -ENOSYS;
359f400b2a4SLin Jinhan 
36036e17db4Stroy.lin 	if (!ops->is_secure || !ops->is_secure(dev)) {
36136e17db4Stroy.lin 		printf("Only secure crypto support fwkey cipher.\n");
36236e17db4Stroy.lin 		return -ENOSYS;
36336e17db4Stroy.lin 	}
36436e17db4Stroy.lin 
365f400b2a4SLin Jinhan 	keylad_dev = keylad_get_device();
366f400b2a4SLin Jinhan 	if (!keylad_dev) {
367f400b2a4SLin Jinhan 		printf("No keylad device found.\n");
368f400b2a4SLin Jinhan 		return -ENOSYS;
369f400b2a4SLin Jinhan 	}
370f400b2a4SLin Jinhan 
371f400b2a4SLin Jinhan 	if (keylad_transfer_fwkey(keylad_dev, crypto_keytable_addr(dev),
372f400b2a4SLin Jinhan 				  ctx->fw_keyid, ctx->key_len)) {
373f400b2a4SLin Jinhan 		printf("Failed to transfer key from keylad.\n");
374f400b2a4SLin Jinhan 		return -ENOSYS;
375f400b2a4SLin Jinhan 	}
376f400b2a4SLin Jinhan 
377f400b2a4SLin Jinhan 	return ops->cipher_fw_crypt(dev, ctx, in, out, len, enc);
378*24a57c1cSLin Jinhan #else
379*24a57c1cSLin Jinhan 	return -ENOSYS;
380*24a57c1cSLin Jinhan #endif
381f400b2a4SLin Jinhan }
382f400b2a4SLin Jinhan 
crypto_keytable_addr(struct udevice * dev)383f400b2a4SLin Jinhan ulong crypto_keytable_addr(struct udevice *dev)
384f400b2a4SLin Jinhan {
385f400b2a4SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
386f400b2a4SLin Jinhan 
387f400b2a4SLin Jinhan 	if (!ops || !ops->keytable_addr)
388f400b2a4SLin Jinhan 		return 0;
389f400b2a4SLin Jinhan 
390f400b2a4SLin Jinhan 	return ops->keytable_addr(dev);
391f400b2a4SLin Jinhan }
392f400b2a4SLin Jinhan 
crypto_is_secure(struct udevice * dev)39336e17db4Stroy.lin bool crypto_is_secure(struct udevice *dev)
39436e17db4Stroy.lin {
39536e17db4Stroy.lin 	const struct dm_crypto_ops *ops = device_get_ops(dev);
39636e17db4Stroy.lin 
39736e17db4Stroy.lin 	if (!ops || !ops->is_secure)
39836e17db4Stroy.lin 		return false;
39936e17db4Stroy.lin 
40036e17db4Stroy.lin 	return ops->is_secure(dev);
40136e17db4Stroy.lin }
40236e17db4Stroy.lin 
403cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = {
404cc6ac5d6SJoseph Chen 	.id	= UCLASS_CRYPTO,
405cc6ac5d6SJoseph Chen 	.name	= "crypto",
406cc6ac5d6SJoseph Chen };
407