xref: /rk3399_rockchip-uboot/drivers/crypto/crypto-uclass.c (revision 6b5b88bc0322ae61aa6ab38a32bc8edadca8e9a0)
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 
8*6b5b88bcSLin Jinhan static const u8 null_hash_sha1_value[] = {
9*6b5b88bcSLin Jinhan 	0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
10*6b5b88bcSLin Jinhan 	0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
11*6b5b88bcSLin Jinhan 	0xaf, 0xd8, 0x07, 0x09
12*6b5b88bcSLin Jinhan };
13*6b5b88bcSLin Jinhan 
14*6b5b88bcSLin Jinhan static const u8 null_hash_md5_value[] = {
15*6b5b88bcSLin Jinhan 	0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
16*6b5b88bcSLin Jinhan 	0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e
17*6b5b88bcSLin Jinhan };
18*6b5b88bcSLin Jinhan 
19*6b5b88bcSLin Jinhan static const u8 null_hash_sha256_value[] = {
20*6b5b88bcSLin Jinhan 	0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
21*6b5b88bcSLin Jinhan 	0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
22*6b5b88bcSLin Jinhan 	0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
23*6b5b88bcSLin Jinhan 	0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
24*6b5b88bcSLin Jinhan };
25*6b5b88bcSLin Jinhan 
26*6b5b88bcSLin Jinhan static const u8 null_hash_sha512_value[] = {
27*6b5b88bcSLin Jinhan 	0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
28*6b5b88bcSLin Jinhan 	0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
29*6b5b88bcSLin Jinhan 	0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
30*6b5b88bcSLin Jinhan 	0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
31*6b5b88bcSLin Jinhan 	0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
32*6b5b88bcSLin Jinhan 	0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
33*6b5b88bcSLin Jinhan 	0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
34*6b5b88bcSLin Jinhan 	0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
35*6b5b88bcSLin Jinhan };
36*6b5b88bcSLin Jinhan 
37cc6ac5d6SJoseph Chen u32 crypto_algo_nbits(u32 algo)
38cc6ac5d6SJoseph Chen {
39cc6ac5d6SJoseph Chen 	switch (algo) {
40cc6ac5d6SJoseph Chen 	case CRYPTO_MD5:
41cc6ac5d6SJoseph Chen 		return 128;
42cc6ac5d6SJoseph Chen 	case CRYPTO_SHA1:
43cc6ac5d6SJoseph Chen 		return 160;
44cc6ac5d6SJoseph Chen 	case CRYPTO_SHA256:
45cc6ac5d6SJoseph Chen 		return 256;
46e7846385SLin Jinhan 	case CRYPTO_SHA512:
47e7846385SLin Jinhan 		return 512;
48cc6ac5d6SJoseph Chen 	case CRYPTO_RSA512:
49cc6ac5d6SJoseph Chen 		return 512;
50cc6ac5d6SJoseph Chen 	case CRYPTO_RSA1024:
51cc6ac5d6SJoseph Chen 		return 1024;
52cc6ac5d6SJoseph Chen 	case CRYPTO_RSA2048:
53cc6ac5d6SJoseph Chen 		return 2048;
54b353a43cSLin Jinhan 	case CRYPTO_RSA3072:
55b353a43cSLin Jinhan 		return 3072;
56b353a43cSLin Jinhan 	case CRYPTO_RSA4096:
57b353a43cSLin Jinhan 		return 4096;
58cc6ac5d6SJoseph Chen 	}
59cc6ac5d6SJoseph Chen 
60cc6ac5d6SJoseph Chen 	printf("Unknown crypto algorithm: 0x%x\n", algo);
61cc6ac5d6SJoseph Chen 
62cc6ac5d6SJoseph Chen 	return 0;
63cc6ac5d6SJoseph Chen }
64cc6ac5d6SJoseph Chen 
65cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability)
66cc6ac5d6SJoseph Chen {
67cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops;
68cc6ac5d6SJoseph Chen 	struct udevice *dev;
69cc6ac5d6SJoseph Chen 	struct uclass *uc;
70cc6ac5d6SJoseph Chen 	int ret;
71cc6ac5d6SJoseph Chen 	u32 cap;
72cc6ac5d6SJoseph Chen 
73cc6ac5d6SJoseph Chen 	ret = uclass_get(UCLASS_CRYPTO, &uc);
74cc6ac5d6SJoseph Chen 	if (ret)
75cc6ac5d6SJoseph Chen 		return NULL;
76cc6ac5d6SJoseph Chen 
77cc6ac5d6SJoseph Chen 	for (uclass_first_device(UCLASS_CRYPTO, &dev);
78cc6ac5d6SJoseph Chen 	     dev;
79cc6ac5d6SJoseph Chen 	     uclass_next_device(&dev)) {
80cc6ac5d6SJoseph Chen 		ops = device_get_ops(dev);
81cc6ac5d6SJoseph Chen 		if (!ops || !ops->capability)
82cc6ac5d6SJoseph Chen 			continue;
83cc6ac5d6SJoseph Chen 
84cc6ac5d6SJoseph Chen 		cap = ops->capability(dev);
85cc6ac5d6SJoseph Chen 		if ((cap & capability) == capability)
86cc6ac5d6SJoseph Chen 			return dev;
87cc6ac5d6SJoseph Chen 	}
88cc6ac5d6SJoseph Chen 
89cc6ac5d6SJoseph Chen 	return NULL;
90cc6ac5d6SJoseph Chen }
91cc6ac5d6SJoseph Chen 
92cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx)
93cc6ac5d6SJoseph Chen {
94cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
95cc6ac5d6SJoseph Chen 
96*6b5b88bcSLin Jinhan 	if (ctx && !ctx->length)
97*6b5b88bcSLin Jinhan 		return 0;
98*6b5b88bcSLin Jinhan 
99cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_init)
100cc6ac5d6SJoseph Chen 		return -ENOSYS;
101cc6ac5d6SJoseph Chen 
102cc6ac5d6SJoseph Chen 	return ops->sha_init(dev, ctx);
103cc6ac5d6SJoseph Chen }
104cc6ac5d6SJoseph Chen 
105cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
106cc6ac5d6SJoseph Chen {
107cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
108cc6ac5d6SJoseph Chen 
109*6b5b88bcSLin Jinhan 	if (!len)
110*6b5b88bcSLin Jinhan 		return 0;
111*6b5b88bcSLin Jinhan 
112cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_update)
113cc6ac5d6SJoseph Chen 		return -ENOSYS;
114cc6ac5d6SJoseph Chen 
115cc6ac5d6SJoseph Chen 	return ops->sha_update(dev, input, len);
116cc6ac5d6SJoseph Chen }
117cc6ac5d6SJoseph Chen 
118cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
119cc6ac5d6SJoseph Chen {
120cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
121*6b5b88bcSLin Jinhan 	const u8 *null_hash = NULL;
122*6b5b88bcSLin Jinhan 	u32 hash_size = 0;
123*6b5b88bcSLin Jinhan 
124*6b5b88bcSLin Jinhan 	if (ctx && !ctx->length && output) {
125*6b5b88bcSLin Jinhan 		switch (ctx->algo) {
126*6b5b88bcSLin Jinhan 		case CRYPTO_MD5:
127*6b5b88bcSLin Jinhan 			null_hash = null_hash_md5_value;
128*6b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_md5_value);
129*6b5b88bcSLin Jinhan 			break;
130*6b5b88bcSLin Jinhan 		case CRYPTO_SHA1:
131*6b5b88bcSLin Jinhan 			null_hash = null_hash_sha1_value;
132*6b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha1_value);
133*6b5b88bcSLin Jinhan 			break;
134*6b5b88bcSLin Jinhan 		case CRYPTO_SHA256:
135*6b5b88bcSLin Jinhan 			null_hash = null_hash_sha256_value;
136*6b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha256_value);
137*6b5b88bcSLin Jinhan 			break;
138*6b5b88bcSLin Jinhan 		case CRYPTO_SHA512:
139*6b5b88bcSLin Jinhan 			null_hash = null_hash_sha512_value;
140*6b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha512_value);
141*6b5b88bcSLin Jinhan 			break;
142*6b5b88bcSLin Jinhan 		default:
143*6b5b88bcSLin Jinhan 			return -EINVAL;
144*6b5b88bcSLin Jinhan 		}
145*6b5b88bcSLin Jinhan 
146*6b5b88bcSLin Jinhan 		memcpy(output, null_hash, hash_size);
147*6b5b88bcSLin Jinhan 
148*6b5b88bcSLin Jinhan 		return 0;
149*6b5b88bcSLin Jinhan 	}
150cc6ac5d6SJoseph Chen 
151cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_final)
152cc6ac5d6SJoseph Chen 		return -ENOSYS;
153cc6ac5d6SJoseph Chen 
154cc6ac5d6SJoseph Chen 	return ops->sha_final(dev, ctx, output);
155cc6ac5d6SJoseph Chen }
156cc6ac5d6SJoseph Chen 
157cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx,
158cc6ac5d6SJoseph Chen 		    char *input, u32 input_len, u8 *output)
159cc6ac5d6SJoseph Chen {
160cc6ac5d6SJoseph Chen 	int ret;
161cc6ac5d6SJoseph Chen 
162cc6ac5d6SJoseph Chen 	ret = crypto_sha_init(dev, ctx);
163cc6ac5d6SJoseph Chen 	if (ret)
164cc6ac5d6SJoseph Chen 		return ret;
165cc6ac5d6SJoseph Chen 
166cc6ac5d6SJoseph Chen 	ret = crypto_sha_update(dev, (u32 *)input, input_len);
167cc6ac5d6SJoseph Chen 	if (ret)
168cc6ac5d6SJoseph Chen 		return ret;
169cc6ac5d6SJoseph Chen 
170cc6ac5d6SJoseph Chen 	ret = crypto_sha_final(dev, ctx, output);
171cc6ac5d6SJoseph Chen 
172cc6ac5d6SJoseph Chen 	return ret;
173cc6ac5d6SJoseph Chen }
174cc6ac5d6SJoseph Chen 
175c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx,
176c14e46abSJoseph Chen 			    const struct image_region region[],
177c14e46abSJoseph Chen 			    int region_count, u8 *output)
178c14e46abSJoseph Chen {
179c14e46abSJoseph Chen 	int i, ret;
180c14e46abSJoseph Chen 
181c14e46abSJoseph Chen 	ctx->length = 0;
182c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++)
183c14e46abSJoseph Chen 		ctx->length += region[i].size;
184c14e46abSJoseph Chen 
185c14e46abSJoseph Chen 	ret = crypto_sha_init(dev, ctx);
186c14e46abSJoseph Chen 	if (ret)
187c14e46abSJoseph Chen 		return ret;
188c14e46abSJoseph Chen 
189c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++) {
190c14e46abSJoseph Chen 		ret = crypto_sha_update(dev, (void *)region[i].data,
191c14e46abSJoseph Chen 					region[i].size);
192c14e46abSJoseph Chen 		if (ret)
193c14e46abSJoseph Chen 			return ret;
194c14e46abSJoseph Chen 	}
195c14e46abSJoseph Chen 
196c14e46abSJoseph Chen 	return crypto_sha_final(dev, ctx, output);
197c14e46abSJoseph Chen }
198c14e46abSJoseph Chen 
199cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output)
200cc6ac5d6SJoseph Chen {
201cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
202cc6ac5d6SJoseph Chen 
203cc6ac5d6SJoseph Chen 	if (!ops || !ops->rsa_verify)
204cc6ac5d6SJoseph Chen 		return -ENOSYS;
205cc6ac5d6SJoseph Chen 
206cc6ac5d6SJoseph Chen 	return ops->rsa_verify(dev, ctx, sign, output);
207cc6ac5d6SJoseph Chen }
208cc6ac5d6SJoseph Chen 
209434d6fd3SLin Jinhan int crypto_get_trng(struct udevice *dev, u8 *output, u32 len)
210434d6fd3SLin Jinhan {
211434d6fd3SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
212434d6fd3SLin Jinhan 
213434d6fd3SLin Jinhan 	if (!ops || !ops->get_trng)
214434d6fd3SLin Jinhan 		return -ENOSYS;
215434d6fd3SLin Jinhan 
216434d6fd3SLin Jinhan 	return ops->get_trng(dev, output, len);
217434d6fd3SLin Jinhan }
218434d6fd3SLin Jinhan 
219cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = {
220cc6ac5d6SJoseph Chen 	.id	= UCLASS_CRYPTO,
221cc6ac5d6SJoseph Chen 	.name	= "crypto",
222cc6ac5d6SJoseph Chen };
223