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