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