xref: /isa-l_crypto/rolling_hash/rolling_hash2.c (revision 1e0b122e090c8ad3a8d8c56e182f754ea26fe70d)
1 /**********************************************************************
2   Copyright(c) 2011-2017 Intel Corporation All rights reserved.
3 
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions
6   are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in
11       the documentation and/or other materials provided with the
12       distribution.
13     * Neither the name of Intel Corporation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include "rolling_hashx.h"
33 #include "rolling_hashx_internal.h"
34 #include "rolling_hash2_table.h"
35 #include "isal_crypto_api.h"
36 
37 extern uint64_t
38 _rolling_hash2_run_until(uint32_t *idx, int max_idx, uint64_t *t1, uint64_t *t2, uint8_t *b1,
39                          uint8_t *b2, uint64_t h, uint64_t mask, uint64_t trigger);
40 
41 int
_rolling_hash2_init(struct isal_rh_state2 * state,uint32_t w)42 _rolling_hash2_init(struct isal_rh_state2 *state, uint32_t w)
43 {
44         uint32_t i;
45         uint64_t v;
46 
47         if (w > ISAL_FINGERPRINT_MAX_WINDOW)
48                 return -1;
49 
50         for (i = 0; i < 256; i++) {
51                 v = rolling_hash2_table1[i];
52                 state->table1[i] = v;
53                 state->table2[i] = (v << w) | (v >> (64 - w));
54         }
55         state->w = w;
56         return 0;
57 }
58 
59 void
_rolling_hash2_reset(struct isal_rh_state2 * state,uint8_t * init_bytes)60 _rolling_hash2_reset(struct isal_rh_state2 *state, uint8_t *init_bytes)
61 {
62         uint64_t hash;
63         uint32_t i, w;
64 
65         hash = 0;
66         w = state->w;
67         for (i = 0; i < w; i++) {
68                 hash = (hash << 1) | (hash >> (64 - 1));
69                 hash ^= state->table1[init_bytes[i]];
70         }
71         state->hash = hash;
72         memcpy(state->history, init_bytes, w);
73 }
74 
75 static uint64_t
hash_fn(struct isal_rh_state2 * state,uint64_t h,uint8_t new_char,uint8_t old_char)76 hash_fn(struct isal_rh_state2 *state, uint64_t h, uint8_t new_char, uint8_t old_char)
77 {
78         h = (h << 1) | (h >> (64 - 1));
79         h ^= state->table1[new_char] ^ state->table2[old_char];
80         return h;
81 }
82 
83 uint64_t
_rolling_hash2_run_until_base(uint32_t * idx,int max_idx,uint64_t * t1,uint64_t * t2,uint8_t * b1,uint8_t * b2,uint64_t h,uint64_t mask,uint64_t trigger)84 _rolling_hash2_run_until_base(uint32_t *idx, int max_idx, uint64_t *t1, uint64_t *t2, uint8_t *b1,
85                               uint8_t *b2, uint64_t h, uint64_t mask, uint64_t trigger)
86 {
87         int i = *idx;
88 
89         if (trigger == 0) {
90                 for (; i < max_idx; i++) {
91                         h = (h << 1) | (h >> (64 - 1));
92                         h ^= t1[b1[i]] ^ t2[b2[i]];
93                         if ((h & mask) == 0) {
94                                 *idx = i;
95                                 return h;
96                         }
97                 }
98         } else {
99                 for (; i < max_idx; i++) {
100                         h = (h << 1) | (h >> (64 - 1));
101                         h ^= t1[b1[i]] ^ t2[b2[i]];
102                         if ((h & mask) == trigger) {
103                                 *idx = i;
104                                 return h;
105                         }
106                 }
107         }
108         *idx = i;
109         return h;
110 }
111 
112 int
_rolling_hash2_run(struct isal_rh_state2 * state,uint8_t * buffer,uint32_t buffer_length,uint32_t mask,uint32_t trigger,uint32_t * offset)113 _rolling_hash2_run(struct isal_rh_state2 *state, uint8_t *buffer, uint32_t buffer_length,
114                    uint32_t mask, uint32_t trigger, uint32_t *offset)
115 {
116 
117         uint32_t i;
118         uint32_t w = state->w;
119         uint64_t hash = state->hash;
120 
121         for (i = 0; i < w; i++) {
122                 if (i == buffer_length) {
123                         *offset = i;
124                         // update history
125                         memmove(state->history, state->history + i, w - i);
126                         memcpy(state->history + w - i, buffer, i);
127                         state->hash = hash;
128                         return ISAL_FINGERPRINT_RET_MAX;
129                 }
130                 hash = hash_fn(state, hash, buffer[i], state->history[i]);
131 
132                 if ((hash & mask) == trigger) {
133                         // found hit
134                         i++;
135                         *offset = i;
136                         memmove(state->history, state->history + i, w - i);
137                         memcpy(state->history + w - i, buffer, i);
138                         state->hash = hash;
139                         return ISAL_FINGERPRINT_RET_HIT;
140                 }
141         }
142 
143         hash = _rolling_hash2_run_until(&i, buffer_length, state->table1, state->table2, buffer,
144                                         buffer - w, hash, mask, trigger);
145         if ((hash & mask) == trigger) {
146                 // found hit
147                 i++;
148                 *offset = i;
149                 memcpy(state->history, buffer + i - w, w);
150                 state->hash = hash;
151                 return ISAL_FINGERPRINT_RET_HIT;
152         }
153         // no hit
154         *offset = i;
155         memcpy(state->history, buffer + i - w, w);
156         state->hash = hash;
157         return ISAL_FINGERPRINT_RET_MAX;
158 }
159 
160 int
isal_rolling_hash2_init(struct isal_rh_state2 * state,const uint32_t w)161 isal_rolling_hash2_init(struct isal_rh_state2 *state, const uint32_t w)
162 {
163 #ifdef FIPS_MODE
164         return ISAL_CRYPTO_ERR_FIPS_INVALID_ALGO;
165 #else
166 #ifdef SAFE_PARAM
167         if (state == NULL)
168                 return ISAL_CRYPTO_ERR_NULL_CTX;
169 #endif
170         if (_rolling_hash2_init(state, w) < 0)
171                 return ISAL_CRYPTO_ERR_WINDOW_SIZE;
172 
173         return 0;
174 #endif
175 }
176 
177 int
isal_rolling_hash2_reset(struct isal_rh_state2 * state,const uint8_t * init_bytes)178 isal_rolling_hash2_reset(struct isal_rh_state2 *state, const uint8_t *init_bytes)
179 {
180 #ifdef FIPS_MODE
181         return ISAL_CRYPTO_ERR_FIPS_INVALID_ALGO;
182 #else
183 #ifdef SAFE_PARAM
184         if (state == NULL)
185                 return ISAL_CRYPTO_ERR_NULL_CTX;
186         if (init_bytes == NULL)
187                 return ISAL_CRYPTO_ERR_NULL_INIT_VAL;
188 #endif
189         _rolling_hash2_reset(state, (uint8_t *) init_bytes);
190 
191         return 0;
192 #endif
193 }
194 
195 int
isal_rolling_hash2_run(struct isal_rh_state2 * state,const uint8_t * buffer,const uint32_t max_len,const uint32_t mask,const uint32_t trigger,uint32_t * offset,int * match)196 isal_rolling_hash2_run(struct isal_rh_state2 *state, const uint8_t *buffer, const uint32_t max_len,
197                        const uint32_t mask, const uint32_t trigger, uint32_t *offset, int *match)
198 {
199 #ifdef FIPS_MODE
200         return ISAL_CRYPTO_ERR_FIPS_INVALID_ALGO;
201 #else
202 #ifdef SAFE_PARAM
203         if (state == NULL)
204                 return ISAL_CRYPTO_ERR_NULL_CTX;
205         if (buffer == NULL)
206                 return ISAL_CRYPTO_ERR_NULL_SRC;
207         if (offset == NULL)
208                 return ISAL_CRYPTO_ERR_NULL_OFFSET;
209         if (match == NULL)
210                 return ISAL_CRYPTO_ERR_NULL_MATCH;
211 #endif
212         *match = _rolling_hash2_run(state, (uint8_t *) buffer, max_len, mask, trigger, offset);
213 
214         return 0;
215 #endif
216 }
217 
218 int
isal_rolling_hashx_mask_gen(const uint32_t mean,const uint32_t shift,uint32_t * mask)219 isal_rolling_hashx_mask_gen(const uint32_t mean, const uint32_t shift, uint32_t *mask)
220 {
221 #ifdef FIPS_MODE
222         return ISAL_CRYPTO_ERR_FIPS_INVALID_ALGO;
223 #else
224 #ifdef SAFE_PARAM
225         if (mask == NULL)
226                 return ISAL_CRYPTO_ERR_NULL_MASK;
227 #endif
228         *mask = _rolling_hashx_mask_gen((long) mean, (int) shift);
229 
230         return 0;
231 #endif
232 }
233 
234 /*
235  * =============================================================================
236  * LEGACY / DEPRECATED API
237  * =============================================================================
238  */
239 
240 int
rolling_hash2_init(struct isal_rh_state2 * state,uint32_t w)241 rolling_hash2_init(struct isal_rh_state2 *state, uint32_t w)
242 {
243         return _rolling_hash2_init(state, w);
244 }
245 
246 void
rolling_hash2_reset(struct isal_rh_state2 * state,uint8_t * init_bytes)247 rolling_hash2_reset(struct isal_rh_state2 *state, uint8_t *init_bytes)
248 {
249         _rolling_hash2_reset(state, init_bytes);
250 }
251 
252 int
rolling_hash2_run(struct isal_rh_state2 * state,uint8_t * buffer,uint32_t max_len,uint32_t mask,uint32_t trigger,uint32_t * offset)253 rolling_hash2_run(struct isal_rh_state2 *state, uint8_t *buffer, uint32_t max_len, uint32_t mask,
254                   uint32_t trigger, uint32_t *offset)
255 {
256         return _rolling_hash2_run(state, buffer, max_len, mask, trigger, offset);
257 }
258 
259 uint32_t
rolling_hashx_mask_gen(long mean,int shift)260 rolling_hashx_mask_gen(long mean, int shift)
261 {
262         return _rolling_hashx_mask_gen(mean, shift);
263 }
264 
265 struct slver {
266         uint16_t snum;
267         uint8_t ver;
268         uint8_t core;
269 };
270 struct slver _rolling_hash2_init_slver_00000264;
271 struct slver _rolling_hash2_init_slver = { 0x0264, 0x00, 0x00 };
272 
273 struct slver _rolling_hash2_reset_slver_00000265;
274 struct slver _rolling_hash2_reset_slver = { 0x0265, 0x00, 0x00 };
275 
276 struct slver _rolling_hash2_run_slver_00000266;
277 struct slver _rolling_hash2_run_slver = { 0x0266, 0x00, 0x00 };
278