xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_hash_cache.c (revision 49a2135e4b869844b65124bf91e88486c793cb1d)
1c48f1acfSLin Jinhan // SPDX-License-Identifier: GPL-2.0
2c48f1acfSLin Jinhan /*
3c48f1acfSLin Jinhan  * Copyright (c) 2020 Rockchip Electronics Co., Ltd
4c48f1acfSLin Jinhan  */
5c48f1acfSLin Jinhan 
6c48f1acfSLin Jinhan #include <common.h>
7c48f1acfSLin Jinhan #include <clk.h>
8c48f1acfSLin Jinhan #include <crypto.h>
9c48f1acfSLin Jinhan 
10c48f1acfSLin Jinhan #include <rockchip/crypto_hash_cache.h>
11c48f1acfSLin Jinhan 
hash_cache_calc(struct crypto_hash_cache * hash_cache,const u8 * data,u32 data_len,u8 is_last)12c48f1acfSLin Jinhan static int hash_cache_calc(struct crypto_hash_cache *hash_cache, const u8 *data,
13c48f1acfSLin Jinhan 			   u32 data_len, u8 is_last)
14c48f1acfSLin Jinhan {
15c48f1acfSLin Jinhan 	crypto_hash_calc direct_calc = hash_cache->direct_calc;
16c48f1acfSLin Jinhan 	int ret = 0;
17c48f1acfSLin Jinhan 
18c48f1acfSLin Jinhan 	if (!hash_cache->cache) {
19c48f1acfSLin Jinhan 		hash_cache->cache = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE,
20c48f1acfSLin Jinhan 						   HASH_CACHE_SIZE);
21c48f1acfSLin Jinhan 		if (!hash_cache->cache)
22c48f1acfSLin Jinhan 			goto error;
23c48f1acfSLin Jinhan 
24c48f1acfSLin Jinhan 		hash_cache->cache_size = 0;
25c48f1acfSLin Jinhan 	}
26c48f1acfSLin Jinhan 
27c48f1acfSLin Jinhan 	while (1) {
28c48f1acfSLin Jinhan 		u32 tmp_len = 0;
29c48f1acfSLin Jinhan 
30c48f1acfSLin Jinhan 		if (hash_cache->cache_size + data_len <= HASH_CACHE_SIZE) {
31c48f1acfSLin Jinhan 			/* copy to cache */
32c48f1acfSLin Jinhan 			debug("%s, %d: copy to cache %u\n",
33c48f1acfSLin Jinhan 			      __func__, __LINE__, data_len);
34c48f1acfSLin Jinhan 			memcpy(hash_cache->cache + hash_cache->cache_size, data,
35c48f1acfSLin Jinhan 			       data_len);
36c48f1acfSLin Jinhan 			hash_cache->cache_size += data_len;
37c48f1acfSLin Jinhan 
38c48f1acfSLin Jinhan 			/* if last one calc cache immediately */
39c48f1acfSLin Jinhan 			if (is_last) {
40c48f1acfSLin Jinhan 				debug("%s, %d: last one calc cache %u\n",
41c48f1acfSLin Jinhan 				      __func__, __LINE__,
42c48f1acfSLin Jinhan 				      hash_cache->cache_size);
43c48f1acfSLin Jinhan 
44c48f1acfSLin Jinhan 				ret = direct_calc(hash_cache->user_data,
45c48f1acfSLin Jinhan 						  hash_cache->cache,
46c48f1acfSLin Jinhan 						  hash_cache->cache_size,
47c48f1acfSLin Jinhan 						  &hash_cache->is_started,
48c48f1acfSLin Jinhan 						  is_last);
49c48f1acfSLin Jinhan 				if (ret)
50c48f1acfSLin Jinhan 					goto error;
51c48f1acfSLin Jinhan 			}
52c48f1acfSLin Jinhan 			break;
53c48f1acfSLin Jinhan 		}
54c48f1acfSLin Jinhan 
55c48f1acfSLin Jinhan 		/* 1. make cache be full */
56c48f1acfSLin Jinhan 		/* 2. calc cache */
57c48f1acfSLin Jinhan 		tmp_len = HASH_CACHE_SIZE - hash_cache->cache_size;
58c48f1acfSLin Jinhan 		debug("%s, %d: make cache be full %u\n",
59c48f1acfSLin Jinhan 		      __func__, __LINE__, tmp_len);
60c48f1acfSLin Jinhan 		memcpy(hash_cache->cache + hash_cache->cache_size,
61c48f1acfSLin Jinhan 		       data, tmp_len);
62c48f1acfSLin Jinhan 
63c48f1acfSLin Jinhan 		ret = direct_calc(hash_cache->user_data, hash_cache->cache,
64c48f1acfSLin Jinhan 				  HASH_CACHE_SIZE, &hash_cache->is_started, 0);
65c48f1acfSLin Jinhan 		if (ret)
66c48f1acfSLin Jinhan 			goto error;
67c48f1acfSLin Jinhan 
68c48f1acfSLin Jinhan 		data += tmp_len;
69c48f1acfSLin Jinhan 		data_len -= tmp_len;
70c48f1acfSLin Jinhan 		hash_cache->cache_size = 0;
71c48f1acfSLin Jinhan 	}
72c48f1acfSLin Jinhan 
73c48f1acfSLin Jinhan 	return ret;
74c48f1acfSLin Jinhan error:
75c48f1acfSLin Jinhan 	return -EINVAL;
76c48f1acfSLin Jinhan }
77c48f1acfSLin Jinhan 
crypto_flush_cacheline(ulong addr,ulong size)78c48f1acfSLin Jinhan void crypto_flush_cacheline(ulong addr, ulong size)
79c48f1acfSLin Jinhan {
80c48f1acfSLin Jinhan 	ulong alignment = CONFIG_SYS_CACHELINE_SIZE;
81c48f1acfSLin Jinhan 	ulong aligned_input, aligned_len;
82c48f1acfSLin Jinhan 
83*49a2135eSLin Jinhan 	if (!addr || !size)
84*49a2135eSLin Jinhan 		return;
85*49a2135eSLin Jinhan 
86c48f1acfSLin Jinhan 	/* Must flush dcache before crypto DMA fetch data region */
87c48f1acfSLin Jinhan 	aligned_input = round_down(addr, alignment);
88c48f1acfSLin Jinhan 	aligned_len = round_up(size + (addr - aligned_input), alignment);
89c48f1acfSLin Jinhan 	flush_cache(aligned_input, aligned_len);
90c48f1acfSLin Jinhan }
91c48f1acfSLin Jinhan 
crypto_hash_cache_alloc(crypto_hash_calc direct_calc,void * user_data,u32 total,u32 data_align,u32 len_align)92c48f1acfSLin Jinhan struct crypto_hash_cache *crypto_hash_cache_alloc(crypto_hash_calc direct_calc,
93c48f1acfSLin Jinhan 						  void *user_data, u32 total,
94c48f1acfSLin Jinhan 						  u32 data_align, u32 len_align)
95c48f1acfSLin Jinhan {
96c48f1acfSLin Jinhan 	struct crypto_hash_cache *hash_cache = NULL;
97c48f1acfSLin Jinhan 
98c48f1acfSLin Jinhan 	if (!direct_calc)
99c48f1acfSLin Jinhan 		return NULL;
100c48f1acfSLin Jinhan 
101c48f1acfSLin Jinhan 	hash_cache = malloc(sizeof(struct crypto_hash_cache));
102c48f1acfSLin Jinhan 	if (!hash_cache)
103c48f1acfSLin Jinhan 		return NULL;
104c48f1acfSLin Jinhan 
105c48f1acfSLin Jinhan 	memset(hash_cache, 0x00, sizeof(*hash_cache));
106c48f1acfSLin Jinhan 
107c48f1acfSLin Jinhan 	hash_cache->direct_calc = direct_calc;
108c48f1acfSLin Jinhan 	hash_cache->user_data   = user_data;
109c48f1acfSLin Jinhan 	hash_cache->data_align  = data_align;
110c48f1acfSLin Jinhan 	hash_cache->len_align   = len_align;
111c48f1acfSLin Jinhan 	hash_cache->left_len	= total;
112c48f1acfSLin Jinhan 
113c48f1acfSLin Jinhan 	return hash_cache;
114c48f1acfSLin Jinhan }
115c48f1acfSLin Jinhan 
crypto_hash_cache_free(struct crypto_hash_cache * hash_cache)116c48f1acfSLin Jinhan void crypto_hash_cache_free(struct crypto_hash_cache *hash_cache)
117c48f1acfSLin Jinhan {
118c48f1acfSLin Jinhan 	if (!hash_cache)
119c48f1acfSLin Jinhan 		return;
120c48f1acfSLin Jinhan 
121c48f1acfSLin Jinhan 	if (hash_cache->cache)
122c48f1acfSLin Jinhan 		free(hash_cache->cache);
123c48f1acfSLin Jinhan 
124c48f1acfSLin Jinhan 	free(hash_cache);
125c48f1acfSLin Jinhan }
126c48f1acfSLin Jinhan 
crypto_hash_update_with_cache(struct crypto_hash_cache * hash_cache,const u8 * data,u32 data_len)127c48f1acfSLin Jinhan int crypto_hash_update_with_cache(struct crypto_hash_cache *hash_cache,
128c48f1acfSLin Jinhan 				  const u8 *data, u32 data_len)
129c48f1acfSLin Jinhan {
130c48f1acfSLin Jinhan 	crypto_hash_calc direct_calc = hash_cache->direct_calc;
131c48f1acfSLin Jinhan 	const u8 *direct_data = NULL, *cache_data = NULL;
132c48f1acfSLin Jinhan 	u32 direct_data_len = 0, cache_data_len = 0;
133c48f1acfSLin Jinhan 	u8 is_last = 0;
134c48f1acfSLin Jinhan 	int ret = 0;
135c48f1acfSLin Jinhan 
136c48f1acfSLin Jinhan 	if (hash_cache->left_len < data_len)
137c48f1acfSLin Jinhan 		goto error;
138c48f1acfSLin Jinhan 
139c48f1acfSLin Jinhan 	is_last = hash_cache->left_len == data_len ? 1 : 0;
140c48f1acfSLin Jinhan 
141c48f1acfSLin Jinhan 	if (!hash_cache->use_cache &&
142c48f1acfSLin Jinhan 	    IS_ALIGNED((ulong)data, hash_cache->data_align)) {
143c48f1acfSLin Jinhan 		direct_data = data;
144c48f1acfSLin Jinhan 		if (IS_ALIGNED(data_len, hash_cache->len_align) || is_last) {
145c48f1acfSLin Jinhan 			/* calc all directly */
146c48f1acfSLin Jinhan 			debug("%s, %d: calc all directly\n",
147c48f1acfSLin Jinhan 			      __func__, __LINE__);
148c48f1acfSLin Jinhan 			direct_data_len = data_len;
149c48f1acfSLin Jinhan 		} else {
150c48f1acfSLin Jinhan 			/* calc some directly calc some in cache */
151c48f1acfSLin Jinhan 			debug("%s, %d: calc some directly calc some in cache\n",
152c48f1acfSLin Jinhan 			      __func__, __LINE__);
153c48f1acfSLin Jinhan 			direct_data_len = round_down((ulong)data_len,
154c48f1acfSLin Jinhan 						     hash_cache->len_align);
155c48f1acfSLin Jinhan 			cache_data = direct_data + direct_data_len;
156c48f1acfSLin Jinhan 			cache_data_len = data_len % hash_cache->len_align;
157c48f1acfSLin Jinhan 			hash_cache->use_cache = 1;
158c48f1acfSLin Jinhan 		}
159c48f1acfSLin Jinhan 	} else {
160c48f1acfSLin Jinhan 		/* calc all in cache */
161c48f1acfSLin Jinhan 		debug("%s, %d: calc all in cache\n", __func__, __LINE__);
162c48f1acfSLin Jinhan 		cache_data = data;
163c48f1acfSLin Jinhan 		cache_data_len = data_len;
164c48f1acfSLin Jinhan 		hash_cache->use_cache = 1;
165c48f1acfSLin Jinhan 	}
166c48f1acfSLin Jinhan 
167c48f1acfSLin Jinhan 	if (direct_data_len) {
168c48f1acfSLin Jinhan 		debug("%s, %d: calc direct data %u\n",
169c48f1acfSLin Jinhan 		      __func__, __LINE__, direct_data_len);
170c48f1acfSLin Jinhan 		ret = direct_calc(hash_cache->user_data,
171c48f1acfSLin Jinhan 				  direct_data, direct_data_len,
172c48f1acfSLin Jinhan 				  &hash_cache->is_started, is_last);
173c48f1acfSLin Jinhan 		if (ret)
174c48f1acfSLin Jinhan 			goto error;
175c48f1acfSLin Jinhan 		hash_cache->left_len -= direct_data_len;
176c48f1acfSLin Jinhan 	}
177c48f1acfSLin Jinhan 
178c48f1acfSLin Jinhan 	if (cache_data_len) {
179c48f1acfSLin Jinhan 		debug("%s, %d: calc cache data %u\n",
180c48f1acfSLin Jinhan 		      __func__, __LINE__, cache_data_len);
181c48f1acfSLin Jinhan 		ret = hash_cache_calc(hash_cache, cache_data,
182c48f1acfSLin Jinhan 				      cache_data_len, is_last);
183c48f1acfSLin Jinhan 		if (ret)
184c48f1acfSLin Jinhan 			goto error;
185c48f1acfSLin Jinhan 		hash_cache->left_len -= cache_data_len;
186c48f1acfSLin Jinhan 	}
187c48f1acfSLin Jinhan 
188c48f1acfSLin Jinhan 	return 0;
189c48f1acfSLin Jinhan error:
190c48f1acfSLin Jinhan 	if (hash_cache->cache) {
191c48f1acfSLin Jinhan 		free(hash_cache->cache);
192c48f1acfSLin Jinhan 		hash_cache->cache = NULL;
193c48f1acfSLin Jinhan 	}
194c48f1acfSLin Jinhan 
195c48f1acfSLin Jinhan 	return -EINVAL;
196c48f1acfSLin Jinhan }
197