xref: /rk3399_rockchip-uboot/drivers/crypto/crypto-uclass.c (revision 02b4cf42aaa565c48c7d751bb8f2578d446dff60)
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;
72*02b4cf42SLin Jinhan 	case CRYPTO_SM2:
73*02b4cf42SLin Jinhan 		return 256;
74*02b4cf42SLin Jinhan 	case CRYPTO_ECC_192R1:
75*02b4cf42SLin Jinhan 		return 192;
76*02b4cf42SLin Jinhan 	case CRYPTO_ECC_224R1:
77*02b4cf42SLin Jinhan 		return 224;
78*02b4cf42SLin Jinhan 	case CRYPTO_ECC_256R1:
79*02b4cf42SLin Jinhan 		return 256;
80cc6ac5d6SJoseph Chen 	}
81cc6ac5d6SJoseph Chen 
82cc6ac5d6SJoseph Chen 	printf("Unknown crypto algorithm: 0x%x\n", algo);
83cc6ac5d6SJoseph Chen 
84cc6ac5d6SJoseph Chen 	return 0;
85cc6ac5d6SJoseph Chen }
86cc6ac5d6SJoseph Chen 
87cc6ac5d6SJoseph Chen struct udevice *crypto_get_device(u32 capability)
88cc6ac5d6SJoseph Chen {
89cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops;
90cc6ac5d6SJoseph Chen 	struct udevice *dev;
91cc6ac5d6SJoseph Chen 	struct uclass *uc;
92cc6ac5d6SJoseph Chen 	int ret;
93cc6ac5d6SJoseph Chen 	u32 cap;
94cc6ac5d6SJoseph Chen 
95cc6ac5d6SJoseph Chen 	ret = uclass_get(UCLASS_CRYPTO, &uc);
96cc6ac5d6SJoseph Chen 	if (ret)
97cc6ac5d6SJoseph Chen 		return NULL;
98cc6ac5d6SJoseph Chen 
99cc6ac5d6SJoseph Chen 	for (uclass_first_device(UCLASS_CRYPTO, &dev);
100cc6ac5d6SJoseph Chen 	     dev;
101cc6ac5d6SJoseph Chen 	     uclass_next_device(&dev)) {
102cc6ac5d6SJoseph Chen 		ops = device_get_ops(dev);
103cc6ac5d6SJoseph Chen 		if (!ops || !ops->capability)
104cc6ac5d6SJoseph Chen 			continue;
105cc6ac5d6SJoseph Chen 
106cc6ac5d6SJoseph Chen 		cap = ops->capability(dev);
107cc6ac5d6SJoseph Chen 		if ((cap & capability) == capability)
108cc6ac5d6SJoseph Chen 			return dev;
109cc6ac5d6SJoseph Chen 	}
110cc6ac5d6SJoseph Chen 
111cc6ac5d6SJoseph Chen 	return NULL;
112cc6ac5d6SJoseph Chen }
113cc6ac5d6SJoseph Chen 
114cc6ac5d6SJoseph Chen int crypto_sha_init(struct udevice *dev, sha_context *ctx)
115cc6ac5d6SJoseph Chen {
116cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
117cc6ac5d6SJoseph Chen 
1186b5b88bcSLin Jinhan 	if (ctx && !ctx->length)
1196b5b88bcSLin Jinhan 		return 0;
1206b5b88bcSLin Jinhan 
121cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_init)
122cc6ac5d6SJoseph Chen 		return -ENOSYS;
123cc6ac5d6SJoseph Chen 
124cc6ac5d6SJoseph Chen 	return ops->sha_init(dev, ctx);
125cc6ac5d6SJoseph Chen }
126cc6ac5d6SJoseph Chen 
127cc6ac5d6SJoseph Chen int crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
128cc6ac5d6SJoseph Chen {
129cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
130cc6ac5d6SJoseph Chen 
1316b5b88bcSLin Jinhan 	if (!len)
1326b5b88bcSLin Jinhan 		return 0;
1336b5b88bcSLin Jinhan 
134cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_update)
135cc6ac5d6SJoseph Chen 		return -ENOSYS;
136cc6ac5d6SJoseph Chen 
137cc6ac5d6SJoseph Chen 	return ops->sha_update(dev, input, len);
138cc6ac5d6SJoseph Chen }
139cc6ac5d6SJoseph Chen 
140cc6ac5d6SJoseph Chen int crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
141cc6ac5d6SJoseph Chen {
142cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
1436b5b88bcSLin Jinhan 	const u8 *null_hash = NULL;
1446b5b88bcSLin Jinhan 	u32 hash_size = 0;
1456b5b88bcSLin Jinhan 
1466b5b88bcSLin Jinhan 	if (ctx && !ctx->length && output) {
1476b5b88bcSLin Jinhan 		switch (ctx->algo) {
1486b5b88bcSLin Jinhan 		case CRYPTO_MD5:
1496b5b88bcSLin Jinhan 			null_hash = null_hash_md5_value;
1506b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_md5_value);
1516b5b88bcSLin Jinhan 			break;
1526b5b88bcSLin Jinhan 		case CRYPTO_SHA1:
1536b5b88bcSLin Jinhan 			null_hash = null_hash_sha1_value;
1546b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha1_value);
1556b5b88bcSLin Jinhan 			break;
1566b5b88bcSLin Jinhan 		case CRYPTO_SHA256:
1576b5b88bcSLin Jinhan 			null_hash = null_hash_sha256_value;
1586b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha256_value);
1596b5b88bcSLin Jinhan 			break;
1606b5b88bcSLin Jinhan 		case CRYPTO_SHA512:
1616b5b88bcSLin Jinhan 			null_hash = null_hash_sha512_value;
1626b5b88bcSLin Jinhan 			hash_size = sizeof(null_hash_sha512_value);
1636b5b88bcSLin Jinhan 			break;
16449a2135eSLin Jinhan 		case CRYPTO_SM3:
16549a2135eSLin Jinhan 			null_hash = null_hash_sm3_value;
16649a2135eSLin Jinhan 			hash_size = sizeof(null_hash_sm3_value);
16749a2135eSLin Jinhan 			break;
1686b5b88bcSLin Jinhan 		default:
1696b5b88bcSLin Jinhan 			return -EINVAL;
1706b5b88bcSLin Jinhan 		}
1716b5b88bcSLin Jinhan 
1726b5b88bcSLin Jinhan 		memcpy(output, null_hash, hash_size);
1736b5b88bcSLin Jinhan 
1746b5b88bcSLin Jinhan 		return 0;
1756b5b88bcSLin Jinhan 	}
176cc6ac5d6SJoseph Chen 
177cc6ac5d6SJoseph Chen 	if (!ops || !ops->sha_final)
178cc6ac5d6SJoseph Chen 		return -ENOSYS;
179cc6ac5d6SJoseph Chen 
180cc6ac5d6SJoseph Chen 	return ops->sha_final(dev, ctx, output);
181cc6ac5d6SJoseph Chen }
182cc6ac5d6SJoseph Chen 
18349a2135eSLin Jinhan int crypto_hmac_init(struct udevice *dev, sha_context *ctx,
18449a2135eSLin Jinhan 		     u8 *key, u32 key_len)
18549a2135eSLin Jinhan {
18649a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
18749a2135eSLin Jinhan 
18849a2135eSLin Jinhan 	if (ctx && !ctx->length)
18949a2135eSLin Jinhan 		return -EINVAL;
19049a2135eSLin Jinhan 
19149a2135eSLin Jinhan 	if (!ops || !ops->hmac_init)
19249a2135eSLin Jinhan 		return -ENOSYS;
19349a2135eSLin Jinhan 
19449a2135eSLin Jinhan 	return ops->hmac_init(dev, ctx, key, key_len);
19549a2135eSLin Jinhan }
19649a2135eSLin Jinhan 
19749a2135eSLin Jinhan int crypto_hmac_update(struct udevice *dev, u32 *input, u32 len)
19849a2135eSLin Jinhan {
19949a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
20049a2135eSLin Jinhan 
20149a2135eSLin Jinhan 	if (!len)
20249a2135eSLin Jinhan 		return 0;
20349a2135eSLin Jinhan 
20449a2135eSLin Jinhan 	if (!ops || !ops->hmac_update)
20549a2135eSLin Jinhan 		return -ENOSYS;
20649a2135eSLin Jinhan 
20749a2135eSLin Jinhan 	return ops->hmac_update(dev, input, len);
20849a2135eSLin Jinhan }
20949a2135eSLin Jinhan 
21049a2135eSLin Jinhan int crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output)
21149a2135eSLin Jinhan {
21249a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
21349a2135eSLin Jinhan 
21449a2135eSLin Jinhan 	if (!ops || !ops->hmac_final)
21549a2135eSLin Jinhan 		return -ENOSYS;
21649a2135eSLin Jinhan 
21749a2135eSLin Jinhan 	return ops->hmac_final(dev, ctx, output);
21849a2135eSLin Jinhan }
21949a2135eSLin Jinhan 
220cc6ac5d6SJoseph Chen int crypto_sha_csum(struct udevice *dev, sha_context *ctx,
221cc6ac5d6SJoseph Chen 		    char *input, u32 input_len, u8 *output)
222cc6ac5d6SJoseph Chen {
223cc6ac5d6SJoseph Chen 	int ret;
224cc6ac5d6SJoseph Chen 
225cc6ac5d6SJoseph Chen 	ret = crypto_sha_init(dev, ctx);
226cc6ac5d6SJoseph Chen 	if (ret)
227cc6ac5d6SJoseph Chen 		return ret;
228cc6ac5d6SJoseph Chen 
229cc6ac5d6SJoseph Chen 	ret = crypto_sha_update(dev, (u32 *)input, input_len);
230cc6ac5d6SJoseph Chen 	if (ret)
231cc6ac5d6SJoseph Chen 		return ret;
232cc6ac5d6SJoseph Chen 
233cc6ac5d6SJoseph Chen 	ret = crypto_sha_final(dev, ctx, output);
234cc6ac5d6SJoseph Chen 
235cc6ac5d6SJoseph Chen 	return ret;
236cc6ac5d6SJoseph Chen }
237cc6ac5d6SJoseph Chen 
238c14e46abSJoseph Chen int crypto_sha_regions_csum(struct udevice *dev, sha_context *ctx,
239c14e46abSJoseph Chen 			    const struct image_region region[],
240c14e46abSJoseph Chen 			    int region_count, u8 *output)
241c14e46abSJoseph Chen {
242c14e46abSJoseph Chen 	int i, ret;
243c14e46abSJoseph Chen 
244c14e46abSJoseph Chen 	ctx->length = 0;
245c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++)
246c14e46abSJoseph Chen 		ctx->length += region[i].size;
247c14e46abSJoseph Chen 
248c14e46abSJoseph Chen 	ret = crypto_sha_init(dev, ctx);
249c14e46abSJoseph Chen 	if (ret)
250c14e46abSJoseph Chen 		return ret;
251c14e46abSJoseph Chen 
252c14e46abSJoseph Chen 	for (i = 0; i < region_count; i++) {
253c14e46abSJoseph Chen 		ret = crypto_sha_update(dev, (void *)region[i].data,
254c14e46abSJoseph Chen 					region[i].size);
255c14e46abSJoseph Chen 		if (ret)
256c14e46abSJoseph Chen 			return ret;
257c14e46abSJoseph Chen 	}
258c14e46abSJoseph Chen 
259c14e46abSJoseph Chen 	return crypto_sha_final(dev, ctx, output);
260c14e46abSJoseph Chen }
261c14e46abSJoseph Chen 
262cc6ac5d6SJoseph Chen int crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, u8 *sign, u8 *output)
263cc6ac5d6SJoseph Chen {
264cc6ac5d6SJoseph Chen 	const struct dm_crypto_ops *ops = device_get_ops(dev);
265cc6ac5d6SJoseph Chen 
266cc6ac5d6SJoseph Chen 	if (!ops || !ops->rsa_verify)
267cc6ac5d6SJoseph Chen 		return -ENOSYS;
268cc6ac5d6SJoseph Chen 
269549a74f7SLin Jinhan 	if (!ctx || !ctx->n || !ctx->e || !sign || !output)
270549a74f7SLin Jinhan 		return -EINVAL;
271549a74f7SLin Jinhan 
272cc6ac5d6SJoseph Chen 	return ops->rsa_verify(dev, ctx, sign, output);
273cc6ac5d6SJoseph Chen }
274cc6ac5d6SJoseph Chen 
275*02b4cf42SLin Jinhan int crypto_ec_verify(struct udevice *dev, ec_key *ctx, u8 *hash, u32 hash_len, u8 *sign)
276*02b4cf42SLin Jinhan {
277*02b4cf42SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
278*02b4cf42SLin Jinhan 
279*02b4cf42SLin Jinhan 	if (!ops || !ops->ec_verify)
280*02b4cf42SLin Jinhan 		return -ENOSYS;
281*02b4cf42SLin Jinhan 
282*02b4cf42SLin Jinhan 	if (!ctx || !ctx->x || !ctx->y || !ctx->y || !hash || hash_len == 0 || !sign)
283*02b4cf42SLin Jinhan 		return -EINVAL;
284*02b4cf42SLin Jinhan 
285*02b4cf42SLin Jinhan 	return ops->ec_verify(dev, ctx, hash, hash_len, sign);
286*02b4cf42SLin Jinhan }
287*02b4cf42SLin Jinhan 
28849a2135eSLin Jinhan int crypto_cipher(struct udevice *dev, cipher_context *ctx,
28949a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
29049a2135eSLin Jinhan {
29149a2135eSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
29249a2135eSLin Jinhan 
29349a2135eSLin Jinhan 	if (!ops || !ops->cipher_crypt)
29449a2135eSLin Jinhan 		return -ENOSYS;
29549a2135eSLin Jinhan 
29649a2135eSLin Jinhan 	return ops->cipher_crypt(dev, ctx, in, out, len, enc);
29749a2135eSLin Jinhan }
29849a2135eSLin Jinhan 
299d9332f1cSLin Jinhan int crypto_mac(struct udevice *dev, cipher_context *ctx,
300d9332f1cSLin Jinhan 	       const u8 *in, u32 len, u8 *tag)
301d9332f1cSLin Jinhan {
302d9332f1cSLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
303d9332f1cSLin Jinhan 
304d9332f1cSLin Jinhan 	if (!ops || !ops->cipher_mac)
305d9332f1cSLin Jinhan 		return -ENOSYS;
306d9332f1cSLin Jinhan 
307d9332f1cSLin Jinhan 	return ops->cipher_mac(dev, ctx, in, len, tag);
308d9332f1cSLin Jinhan }
309d9332f1cSLin Jinhan 
310c3ce9937SLin Jinhan int crypto_ae(struct udevice *dev, cipher_context *ctx,
311c3ce9937SLin Jinhan 	      const u8 *in, u32 len, const u8 *aad, u32 aad_len,
312c3ce9937SLin Jinhan 	      u8 *out, u8 *tag)
313c3ce9937SLin Jinhan {
314c3ce9937SLin Jinhan 	const struct dm_crypto_ops *ops = device_get_ops(dev);
315c3ce9937SLin Jinhan 
316c3ce9937SLin Jinhan 	if (!ops || !ops->cipher_ae)
317c3ce9937SLin Jinhan 		return -ENOSYS;
318c3ce9937SLin Jinhan 
319c3ce9937SLin Jinhan 	return ops->cipher_ae(dev, ctx, in, len, aad, aad_len, out, tag);
320c3ce9937SLin Jinhan }
321c3ce9937SLin Jinhan 
322cc6ac5d6SJoseph Chen UCLASS_DRIVER(crypto) = {
323cc6ac5d6SJoseph Chen 	.id	= UCLASS_CRYPTO,
324cc6ac5d6SJoseph Chen 	.name	= "crypto",
325cc6ac5d6SJoseph Chen };
326