xref: /rk3399_rockchip-uboot/drivers/crypto/crypto-uclass.c (revision c3ce993789b241f7bfc245002cbdd7d111499e3f)
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>
7cc6ac5d6SJoseph Chen 
86b5b88bcSLin Jinhan static const u8 null_hash_sha1_value[] = {
96b5b88bcSLin Jinhan 	0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
106b5b88bcSLin Jinhan 	0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
116b5b88bcSLin Jinhan 	0xaf, 0xd8, 0x07, 0x09
126b5b88bcSLin Jinhan };
136b5b88bcSLin Jinhan 
146b5b88bcSLin Jinhan static const u8 null_hash_md5_value[] = {
156b5b88bcSLin Jinhan 	0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
166b5b88bcSLin Jinhan 	0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
176b5b88bcSLin Jinhan };
186b5b88bcSLin Jinhan 
196b5b88bcSLin Jinhan static const u8 null_hash_sha256_value[] = {
206b5b88bcSLin Jinhan 	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
216b5b88bcSLin Jinhan 	0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
226b5b88bcSLin Jinhan 	0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
236b5b88bcSLin Jinhan 	0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
246b5b88bcSLin Jinhan };
256b5b88bcSLin Jinhan 
266b5b88bcSLin Jinhan static const u8 null_hash_sha512_value[] = {
276b5b88bcSLin Jinhan 	0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
286b5b88bcSLin Jinhan 	0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
296b5b88bcSLin Jinhan 	0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
306b5b88bcSLin Jinhan 	0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
316b5b88bcSLin Jinhan 	0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
326b5b88bcSLin Jinhan 	0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
336b5b88bcSLin Jinhan 	0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
346b5b88bcSLin Jinhan 	0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
356b5b88bcSLin Jinhan };
366b5b88bcSLin Jinhan 
3749a2135eSLin Jinhan const static u8 null_hash_sm3_value[] = {
3849a2135eSLin Jinhan 	0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f,
3949a2135eSLin Jinhan 	0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f,
4049a2135eSLin Jinhan 	0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74,
4149a2135eSLin Jinhan 	0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b
4249a2135eSLin Jinhan };
4349a2135eSLin Jinhan 
44cc6ac5d6SJoseph Chen u32 crypto_algo_nbits(u32 algo)
45cc6ac5d6SJoseph Chen {
46cc6ac5d6SJoseph Chen 	switch (algo) {
47cc6ac5d6SJoseph Chen 	case CRYPTO_MD5:
4849a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
49cc6ac5d6SJoseph Chen 		return 128;
50cc6ac5d6SJoseph Chen 	case CRYPTO_SHA1:
5149a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
52cc6ac5d6SJoseph Chen 		return 160;
53cc6ac5d6SJoseph Chen 	case CRYPTO_SHA256:
5449a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
55cc6ac5d6SJoseph Chen 		return 256;
56e7846385SLin Jinhan 	case CRYPTO_SHA512:
5749a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
58e7846385SLin Jinhan 		return 512;
5949a2135eSLin Jinhan 	case CRYPTO_SM3:
6049a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
6149a2135eSLin Jinhan 		return 256;
62cc6ac5d6SJoseph Chen 	case CRYPTO_RSA512:
63cc6ac5d6SJoseph Chen 		return 512;
64cc6ac5d6SJoseph Chen 	case CRYPTO_RSA1024:
65cc6ac5d6SJoseph Chen 		return 1024;
66cc6ac5d6SJoseph Chen 	case CRYPTO_RSA2048:
67cc6ac5d6SJoseph Chen 		return 2048;
68b353a43cSLin Jinhan 	case CRYPTO_RSA3072:
69b353a43cSLin Jinhan 		return 3072;
70b353a43cSLin Jinhan 	case CRYPTO_RSA4096:
71b353a43cSLin Jinhan 		return 4096;
72cc6ac5d6SJoseph Chen 	}
73cc6ac5d6SJoseph Chen 
74cc6ac5d6SJoseph Chen 	printf("Unknown crypto algorithm: 0x%x\n", algo);
75cc6ac5d6SJoseph Chen 
76cc6ac5d6SJoseph Chen 	return 0;
77cc6ac5d6SJoseph Chen }
78cc6ac5d6SJoseph Chen 
79cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability)
80cc6ac5d6SJoseph Chen {
81cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops;
82cc6ac5d6SJoseph Chen 	struct udevice *dev;
83cc6ac5d6SJoseph Chen 	struct uclass *uc;
84cc6ac5d6SJoseph Chen 	int ret;
85cc6ac5d6SJoseph Chen 	u32 cap;
86cc6ac5d6SJoseph Chen 
87cc6ac5d6SJoseph Chen 	ret = uclass_get(UCLASS_CRYPTO, &uc);
88cc6ac5d6SJoseph Chen 	if (ret)
89cc6ac5d6SJoseph Chen 		return NULL;
90cc6ac5d6SJoseph Chen 
91cc6ac5d6SJoseph Chen 	for (uclass_first_device(UCLASS_CRYPTO, &dev);
92cc6ac5d6SJoseph Chen 	     dev;
93cc6ac5d6SJoseph Chen 	     uclass_next_device(&dev)) {
94cc6ac5d6SJoseph Chen 		ops = device_get_ops(dev);
95cc6ac5d6SJoseph Chen 		if (!ops || !ops->capability)
96cc6ac5d6SJoseph Chen 			continue;
97cc6ac5d6SJoseph Chen 
98cc6ac5d6SJoseph Chen 		cap = ops->capability(dev);
99cc6ac5d6SJoseph Chen 		if ((cap & capability) == capability)
100cc6ac5d6SJoseph Chen 			return dev;
101cc6ac5d6SJoseph Chen 	}
102cc6ac5d6SJoseph Chen 
103cc6ac5d6SJoseph Chen 	return NULL;
104cc6ac5d6SJoseph Chen }
105cc6ac5d6SJoseph Chen 
106cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx)
107cc6ac5d6SJoseph Chen {
108cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
109cc6ac5d6SJoseph Chen 
1106b5b88bcSLin Jinhan 	if (ctx && !ctx->length)
1116b5b88bcSLin Jinhan 		return 0;
1126b5b88bcSLin Jinhan 
113cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_init)
114cc6ac5d6SJoseph Chen 		return -ENOSYS;
115cc6ac5d6SJoseph Chen 
116cc6ac5d6SJoseph Chen 	return ops->sha_init(dev, ctx);
117cc6ac5d6SJoseph Chen }
118cc6ac5d6SJoseph Chen 
119cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
120cc6ac5d6SJoseph Chen {
121cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
122cc6ac5d6SJoseph Chen 
1236b5b88bcSLin Jinhan 	if (!len)
1246b5b88bcSLin Jinhan 		return 0;
1256b5b88bcSLin Jinhan 
126cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_update)
127cc6ac5d6SJoseph Chen 		return -ENOSYS;
128cc6ac5d6SJoseph Chen 
129cc6ac5d6SJoseph Chen 	return ops->sha_update(dev, input, len);
130cc6ac5d6SJoseph Chen }
131cc6ac5d6SJoseph Chen 
132cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
133cc6ac5d6SJoseph Chen {
134cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
1356b5b88bcSLin Jinhan 	const u8 *null_hash = NULL;
1366b5b88bcSLin Jinhan 	u32 hash_size = 0;
1376b5b88bcSLin Jinhan 
1386b5b88bcSLin Jinhan 	if (ctx && !ctx->length && output) {
1396b5b88bcSLin Jinhan 		switch (ctx->algo) {
1406b5b88bcSLin Jinhan 		case CRYPTO_MD5:
1416b5b88bcSLin Jinhan 			null_hash = null_hash_md5_value;
1426b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_md5_value);
1436b5b88bcSLin Jinhan 			break;
1446b5b88bcSLin Jinhan 		case CRYPTO_SHA1:
1456b5b88bcSLin Jinhan 			null_hash = null_hash_sha1_value;
1466b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha1_value);
1476b5b88bcSLin Jinhan 			break;
1486b5b88bcSLin Jinhan 		case CRYPTO_SHA256:
1496b5b88bcSLin Jinhan 			null_hash = null_hash_sha256_value;
1506b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha256_value);
1516b5b88bcSLin Jinhan 			break;
1526b5b88bcSLin Jinhan 		case CRYPTO_SHA512:
1536b5b88bcSLin Jinhan 			null_hash = null_hash_sha512_value;
1546b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha512_value);
1556b5b88bcSLin Jinhan 			break;
15649a2135eSLin Jinhan 		case CRYPTO_SM3:
15749a2135eSLin Jinhan 			null_hash = null_hash_sm3_value;
15849a2135eSLin Jinhan 			hash_size = sizeof(null_hash_sm3_value);
15949a2135eSLin Jinhan 			break;
1606b5b88bcSLin Jinhan 		default:
1616b5b88bcSLin Jinhan 			return -EINVAL;
1626b5b88bcSLin Jinhan 		}
1636b5b88bcSLin Jinhan 
1646b5b88bcSLin Jinhan 		memcpy(output, null_hash, hash_size);
1656b5b88bcSLin Jinhan 
1666b5b88bcSLin Jinhan 		return 0;
1676b5b88bcSLin Jinhan 	}
168cc6ac5d6SJoseph Chen 
169cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_final)
170cc6ac5d6SJoseph Chen 		return -ENOSYS;
171cc6ac5d6SJoseph Chen 
172cc6ac5d6SJoseph Chen 	return ops->sha_final(dev, ctx, output);
173cc6ac5d6SJoseph Chen }
174cc6ac5d6SJoseph Chen 
17549a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx,
17649a2135eSLin Jinhan 		     u8 *key, u32 key_len)
17749a2135eSLin Jinhan {
17849a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
17949a2135eSLin Jinhan 
18049a2135eSLin Jinhan 	if (ctx && !ctx->length)
18149a2135eSLin Jinhan 		return -EINVAL;
18249a2135eSLin Jinhan 
18349a2135eSLin Jinhan 	if (!ops || !ops->hmac_init)
18449a2135eSLin Jinhan 		return -ENOSYS;
18549a2135eSLin Jinhan 
18649a2135eSLin Jinhan 	return ops->hmac_init(dev, ctx, key, key_len);
18749a2135eSLin Jinhan }
18849a2135eSLin Jinhan 
18949a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len)
19049a2135eSLin Jinhan {
19149a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
19249a2135eSLin Jinhan 
19349a2135eSLin Jinhan 	if (!len)
19449a2135eSLin Jinhan 		return 0;
19549a2135eSLin Jinhan 
19649a2135eSLin Jinhan 	if (!ops || !ops->hmac_update)
19749a2135eSLin Jinhan 		return -ENOSYS;
19849a2135eSLin Jinhan 
19949a2135eSLin Jinhan 	return ops->hmac_update(dev, input, len);
20049a2135eSLin Jinhan }
20149a2135eSLin Jinhan 
20249a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output)
20349a2135eSLin Jinhan {
20449a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
20549a2135eSLin Jinhan 
20649a2135eSLin Jinhan 	if (!ops || !ops->hmac_final)
20749a2135eSLin Jinhan 		return -ENOSYS;
20849a2135eSLin Jinhan 
20949a2135eSLin Jinhan 	return ops->hmac_final(dev, ctx, output);
21049a2135eSLin Jinhan }
21149a2135eSLin Jinhan 
212cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx,
213cc6ac5d6SJoseph Chen 		    char *input, u32 input_len, u8 *output)
214cc6ac5d6SJoseph Chen {
215cc6ac5d6SJoseph Chen 	int ret;
216cc6ac5d6SJoseph Chen 
217cc6ac5d6SJoseph Chen 	ret = crypto_sha_init(dev, ctx);
218cc6ac5d6SJoseph Chen 	if (ret)
219cc6ac5d6SJoseph Chen 		return ret;
220cc6ac5d6SJoseph Chen 
221cc6ac5d6SJoseph Chen 	ret = crypto_sha_update(dev, (u32 *)input, input_len);
222cc6ac5d6SJoseph Chen 	if (ret)
223cc6ac5d6SJoseph Chen 		return ret;
224cc6ac5d6SJoseph Chen 
225cc6ac5d6SJoseph Chen 	ret = crypto_sha_final(dev, ctx, output);
226cc6ac5d6SJoseph Chen 
227cc6ac5d6SJoseph Chen 	return ret;
228cc6ac5d6SJoseph Chen }
229cc6ac5d6SJoseph Chen 
230c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx,
231c14e46abSJoseph Chen 			    const struct image_region region[],
232c14e46abSJoseph Chen 			    int region_count, u8 *output)
233c14e46abSJoseph Chen {
234c14e46abSJoseph Chen 	int i, ret;
235c14e46abSJoseph Chen 
236c14e46abSJoseph Chen 	ctx->length = 0;
237c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++)
238c14e46abSJoseph Chen 		ctx->length += region[i].size;
239c14e46abSJoseph Chen 
240c14e46abSJoseph Chen 	ret = crypto_sha_init(dev, ctx);
241c14e46abSJoseph Chen 	if (ret)
242c14e46abSJoseph Chen 		return ret;
243c14e46abSJoseph Chen 
244c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++) {
245c14e46abSJoseph Chen 		ret = crypto_sha_update(dev, (void *)region[i].data,
246c14e46abSJoseph Chen 					region[i].size);
247c14e46abSJoseph Chen 		if (ret)
248c14e46abSJoseph Chen 			return ret;
249c14e46abSJoseph Chen 	}
250c14e46abSJoseph Chen 
251c14e46abSJoseph Chen 	return crypto_sha_final(dev, ctx, output);
252c14e46abSJoseph Chen }
253c14e46abSJoseph Chen 
254cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output)
255cc6ac5d6SJoseph Chen {
256cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
257cc6ac5d6SJoseph Chen 
258cc6ac5d6SJoseph Chen 	if (!ops || !ops->rsa_verify)
259cc6ac5d6SJoseph Chen 		return -ENOSYS;
260cc6ac5d6SJoseph Chen 
261cc6ac5d6SJoseph Chen 	return ops->rsa_verify(dev, ctx, sign, output);
262cc6ac5d6SJoseph Chen }
263cc6ac5d6SJoseph Chen 
26449a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx,
26549a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
26649a2135eSLin Jinhan {
26749a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
26849a2135eSLin Jinhan 
26949a2135eSLin Jinhan 	if (!ops || !ops->cipher_crypt)
27049a2135eSLin Jinhan 		return -ENOSYS;
27149a2135eSLin Jinhan 
27249a2135eSLin Jinhan 	return ops->cipher_crypt(dev, ctx, in, out, len, enc);
27349a2135eSLin Jinhan }
27449a2135eSLin Jinhan 
275d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx,
276d9332f1cSLin Jinhan 	       const u8 *in, u32 len, u8 *tag)
277d9332f1cSLin Jinhan {
278d9332f1cSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
279d9332f1cSLin Jinhan 
280d9332f1cSLin Jinhan 	if (!ops || !ops->cipher_mac)
281d9332f1cSLin Jinhan 		return -ENOSYS;
282d9332f1cSLin Jinhan 
283d9332f1cSLin Jinhan 	return ops->cipher_mac(dev, ctx, in, len, tag);
284d9332f1cSLin Jinhan }
285d9332f1cSLin Jinhan 
286*c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx,
287*c3ce9937SLin Jinhan 	      const u8 *in, u32 len, const u8 *aad, u32 aad_len,
288*c3ce9937SLin Jinhan 	      u8 *out, u8 *tag)
289*c3ce9937SLin Jinhan {
290*c3ce9937SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
291*c3ce9937SLin Jinhan 
292*c3ce9937SLin Jinhan 	if (!ops || !ops->cipher_ae)
293*c3ce9937SLin Jinhan 		return -ENOSYS;
294*c3ce9937SLin Jinhan 
295*c3ce9937SLin Jinhan 	return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag);
296*c3ce9937SLin Jinhan }
297*c3ce9937SLin Jinhan 
298cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = {
299cc6ac5d6SJoseph Chen 	.id	= UCLASS_CRYPTO,
300cc6ac5d6SJoseph Chen 	.name	= "crypto",
301cc6ac5d6SJoseph Chen };
302