153dc9fa0SGreg Tucker /**********************************************************************
253dc9fa0SGreg Tucker Copyright(c) 2011-2017 Intel Corporation All rights reserved.
353dc9fa0SGreg Tucker
453dc9fa0SGreg Tucker Redistribution and use in source and binary forms, with or without
553dc9fa0SGreg Tucker modification, are permitted provided that the following conditions
653dc9fa0SGreg Tucker are met:
753dc9fa0SGreg Tucker * Redistributions of source code must retain the above copyright
853dc9fa0SGreg Tucker notice, this list of conditions and the following disclaimer.
953dc9fa0SGreg Tucker * Redistributions in binary form must reproduce the above copyright
1053dc9fa0SGreg Tucker notice, this list of conditions and the following disclaimer in
1153dc9fa0SGreg Tucker the documentation and/or other materials provided with the
1253dc9fa0SGreg Tucker distribution.
1353dc9fa0SGreg Tucker * Neither the name of Intel Corporation nor the names of its
1453dc9fa0SGreg Tucker contributors may be used to endorse or promote products derived
1553dc9fa0SGreg Tucker from this software without specific prior written permission.
1653dc9fa0SGreg Tucker
1753dc9fa0SGreg Tucker THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1853dc9fa0SGreg Tucker "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1953dc9fa0SGreg Tucker LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2053dc9fa0SGreg Tucker A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2153dc9fa0SGreg Tucker OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2253dc9fa0SGreg Tucker SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2353dc9fa0SGreg Tucker LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2453dc9fa0SGreg Tucker DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2553dc9fa0SGreg Tucker THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2653dc9fa0SGreg Tucker (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2753dc9fa0SGreg Tucker OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2853dc9fa0SGreg Tucker **********************************************************************/
2953dc9fa0SGreg Tucker
3053dc9fa0SGreg Tucker #include <stdlib.h>
3153dc9fa0SGreg Tucker #include <stdint.h>
3253dc9fa0SGreg Tucker #include <string.h>
3353dc9fa0SGreg Tucker #include <stdio.h>
3477e513c6SMarcel Cornu #include "isal_crypto_api.h"
3553dc9fa0SGreg Tucker #include "rolling_hashx.h"
3653dc9fa0SGreg Tucker
3753dc9fa0SGreg Tucker #ifndef FUT_run
3877e513c6SMarcel Cornu #define FUT_run isal_rolling_hash2_run
3953dc9fa0SGreg Tucker #endif
4053dc9fa0SGreg Tucker #ifndef FUT_init
4177e513c6SMarcel Cornu #define FUT_init isal_rolling_hash2_init
4253dc9fa0SGreg Tucker #endif
4353dc9fa0SGreg Tucker #ifndef FUT_reset
4477e513c6SMarcel Cornu #define FUT_reset isal_rolling_hash2_reset
4553dc9fa0SGreg Tucker #endif
4653dc9fa0SGreg Tucker #ifndef FUT_ref
4753dc9fa0SGreg Tucker #define FUT_ref rolling_hash2_ref
4853dc9fa0SGreg Tucker #endif
4953dc9fa0SGreg Tucker
5053dc9fa0SGreg Tucker #define str(s) #s
5153dc9fa0SGreg Tucker #define xstr(s) str(s)
5253dc9fa0SGreg Tucker
5353dc9fa0SGreg Tucker #define MAX_BUFFER_SIZE 128 * 1024 * 1024
5453dc9fa0SGreg Tucker #define MAX_ROLLING_HASH_WIDTH 32
5553dc9fa0SGreg Tucker
5653dc9fa0SGreg Tucker #ifndef RANDOMS
5753dc9fa0SGreg Tucker #define RANDOMS 200
5853dc9fa0SGreg Tucker #endif
5953dc9fa0SGreg Tucker #ifndef TEST_SEED
6053dc9fa0SGreg Tucker #define TEST_SEED 0x1234
6153dc9fa0SGreg Tucker #endif
6253dc9fa0SGreg Tucker
638c212bb2SPablo de Lara #ifndef FIPS_MODE
6459ca9063SMarcel Cornu static uint64_t
rolling_hash2_ref(struct isal_rh_state2 * state,unsigned char * p,int len,uint64_t hash_init)65*1e0b122eSMarcel Cornu rolling_hash2_ref(struct isal_rh_state2 *state, unsigned char *p, int len, uint64_t hash_init)
6653dc9fa0SGreg Tucker {
6753dc9fa0SGreg Tucker int i;
6853dc9fa0SGreg Tucker uint64_t h = hash_init;
6953dc9fa0SGreg Tucker
7053dc9fa0SGreg Tucker for (i = 0; i < len; i++) {
7153dc9fa0SGreg Tucker h = (h << 1) | (h >> (64 - 1));
7253dc9fa0SGreg Tucker h ^= state->table1[*p++];
7353dc9fa0SGreg Tucker }
7453dc9fa0SGreg Tucker return h;
7553dc9fa0SGreg Tucker }
7653dc9fa0SGreg Tucker
778c212bb2SPablo de Lara static int
ones_in_mask(uint32_t in)7859ca9063SMarcel Cornu ones_in_mask(uint32_t in)
7953dc9fa0SGreg Tucker {
8053dc9fa0SGreg Tucker int count;
8153dc9fa0SGreg Tucker
8253dc9fa0SGreg Tucker for (count = 0; in != 0; in &= (in - 1))
8353dc9fa0SGreg Tucker count++;
8453dc9fa0SGreg Tucker
8553dc9fa0SGreg Tucker return count;
8653dc9fa0SGreg Tucker }
8753dc9fa0SGreg Tucker
8853dc9fa0SGreg Tucker /*
8953dc9fa0SGreg Tucker * Utility function to pick a random mask. Not uniform in number of bits.
9053dc9fa0SGreg Tucker */
918c212bb2SPablo de Lara static uint32_t
pick_rand_mask_in_range(int min_bits,int max_bits)9259ca9063SMarcel Cornu pick_rand_mask_in_range(int min_bits, int max_bits)
9353dc9fa0SGreg Tucker {
9453dc9fa0SGreg Tucker uint32_t mask = 0;
9553dc9fa0SGreg Tucker int ones;
9653dc9fa0SGreg Tucker
9753dc9fa0SGreg Tucker do {
9853dc9fa0SGreg Tucker mask = rand();
993a9aded5SGreg Tucker #if defined(_WIN32) || defined(_WIN64)
10053dc9fa0SGreg Tucker mask = (mask << 16) ^ rand();
10153dc9fa0SGreg Tucker #endif
10253dc9fa0SGreg Tucker ones = ones_in_mask(mask);
10353dc9fa0SGreg Tucker } while (ones < min_bits || ones > max_bits);
10453dc9fa0SGreg Tucker
10553dc9fa0SGreg Tucker return mask;
10653dc9fa0SGreg Tucker }
1078c212bb2SPablo de Lara #endif
10853dc9fa0SGreg Tucker
10959ca9063SMarcel Cornu int
main(void)11059ca9063SMarcel Cornu main(void)
11153dc9fa0SGreg Tucker {
1128c212bb2SPablo de Lara #ifndef FIPS_MODE
11353dc9fa0SGreg Tucker uint8_t *buffer;
11453dc9fa0SGreg Tucker uint64_t hash;
115122c1779SMarcel Cornu uint32_t w, max, mask, trigger, offset = 0;
11677e513c6SMarcel Cornu int i, r, ret, match, errors = 0;
11753dc9fa0SGreg Tucker uint32_t offset_fut;
118*1e0b122eSMarcel Cornu struct isal_rh_state2 state;
11953dc9fa0SGreg Tucker
12053dc9fa0SGreg Tucker printf(xstr(FUT_run) ": " xstr(MAX_BUFFER_SIZE));
12153dc9fa0SGreg Tucker
12253dc9fa0SGreg Tucker buffer = malloc(MAX_BUFFER_SIZE);
12353dc9fa0SGreg Tucker if (buffer == NULL) {
12453dc9fa0SGreg Tucker printf("cannot allocate mem\n");
12553dc9fa0SGreg Tucker return -1;
12653dc9fa0SGreg Tucker }
12753dc9fa0SGreg Tucker srand(TEST_SEED);
12853dc9fa0SGreg Tucker
12953dc9fa0SGreg Tucker // Test case 1, compare trigger case at boundary with reference hash
13053dc9fa0SGreg Tucker w = 32;
13153dc9fa0SGreg Tucker mask = 0xffff0;
13253dc9fa0SGreg Tucker trigger = 0x3df0;
13353dc9fa0SGreg Tucker trigger &= mask;
13453dc9fa0SGreg Tucker
13553dc9fa0SGreg Tucker for (i = 0; i < MAX_BUFFER_SIZE; i++)
13653dc9fa0SGreg Tucker buffer[i] = rand();
13753dc9fa0SGreg Tucker
13853dc9fa0SGreg Tucker FUT_init(&state, w);
13953dc9fa0SGreg Tucker FUT_reset(&state, buffer);
14053dc9fa0SGreg Tucker
14153dc9fa0SGreg Tucker uint8_t *p = buffer;
142122c1779SMarcel Cornu uint32_t remain = MAX_BUFFER_SIZE;
1430200e16bSMarcel Cornu match = ISAL_FINGERPRINT_RET_HIT;
14453dc9fa0SGreg Tucker
1450200e16bSMarcel Cornu while ((match == ISAL_FINGERPRINT_RET_HIT) && (remain > 0)) {
14677e513c6SMarcel Cornu ret = FUT_run(&state, p, remain, mask, trigger, &offset, &match);
14777e513c6SMarcel Cornu
14877e513c6SMarcel Cornu if (ret != ISAL_CRYPTO_ERR_NONE) {
14977e513c6SMarcel Cornu printf(" %s (TC1) returned error %d\n", xstr(FUT_run), ret);
15077e513c6SMarcel Cornu errors++;
15177e513c6SMarcel Cornu }
15253dc9fa0SGreg Tucker
15353dc9fa0SGreg Tucker if (offset > remain) {
15453dc9fa0SGreg Tucker printf(" error offset past remaining limit\n");
15553dc9fa0SGreg Tucker errors++;
15653dc9fa0SGreg Tucker }
15753dc9fa0SGreg Tucker
1580200e16bSMarcel Cornu if ((match == ISAL_FINGERPRINT_RET_HIT) && (&p[offset] > &buffer[w])) {
15953dc9fa0SGreg Tucker hash = FUT_ref(&state, &p[offset] - w, w, 0);
16053dc9fa0SGreg Tucker if ((hash & mask) != trigger) {
16153dc9fa0SGreg Tucker printf(" mismatch chunk from ref");
16287dde3adSTomasz Kantecki printf(" hit: offset=%u %llx %llx\n", (unsigned) offset,
16387dde3adSTomasz Kantecki (unsigned long long) state.hash, (unsigned long long) hash);
16453dc9fa0SGreg Tucker errors++;
16553dc9fa0SGreg Tucker }
16653dc9fa0SGreg Tucker }
16753dc9fa0SGreg Tucker p += offset;
16853dc9fa0SGreg Tucker remain -= offset;
16953dc9fa0SGreg Tucker putchar('.');
17053dc9fa0SGreg Tucker }
17153dc9fa0SGreg Tucker
17253dc9fa0SGreg Tucker putchar('.'); // Finished test 1
17353dc9fa0SGreg Tucker
17453dc9fa0SGreg Tucker // Test case 2, check if reference function hits same chunk boundary as test
17553dc9fa0SGreg Tucker
17653dc9fa0SGreg Tucker w = 32;
17753dc9fa0SGreg Tucker mask = 0xffff;
17853dc9fa0SGreg Tucker trigger = rand();
17953dc9fa0SGreg Tucker trigger &= mask;
18053dc9fa0SGreg Tucker p = buffer;
18153dc9fa0SGreg Tucker
18253dc9fa0SGreg Tucker // Function under test
18353dc9fa0SGreg Tucker FUT_init(&state, w);
18453dc9fa0SGreg Tucker FUT_reset(&state, p);
18577e513c6SMarcel Cornu FUT_run(&state, p + w, MAX_BUFFER_SIZE - w, mask, trigger, &offset_fut, &match);
18653dc9fa0SGreg Tucker offset_fut += w;
18753dc9fa0SGreg Tucker
18853dc9fa0SGreg Tucker // Reference
18953dc9fa0SGreg Tucker for (p++, offset = w + 1; offset < MAX_BUFFER_SIZE; offset++) {
19053dc9fa0SGreg Tucker hash = FUT_ref(&state, p++, w, 0);
19153dc9fa0SGreg Tucker if ((hash & mask) == trigger)
19253dc9fa0SGreg Tucker break;
19353dc9fa0SGreg Tucker }
19453dc9fa0SGreg Tucker
19553dc9fa0SGreg Tucker if (offset != offset_fut) {
19653dc9fa0SGreg Tucker printf("\ncase 2, offset of chunk different from ref\n");
19753dc9fa0SGreg Tucker printf(" case 2: stop fut at offset=%d\n", offset_fut);
19853dc9fa0SGreg Tucker printf(" case 2: stop ref at offset=%d\n", offset);
19953dc9fa0SGreg Tucker errors++;
2004c98a7e1SMarcel Cornu goto end;
20153dc9fa0SGreg Tucker }
20253dc9fa0SGreg Tucker putchar('.'); // Finished test 2
20353dc9fa0SGreg Tucker
20453dc9fa0SGreg Tucker // Do case 2 above with random args
20553dc9fa0SGreg Tucker
20653dc9fa0SGreg Tucker for (r = 0; r < RANDOMS; r++) {
20753dc9fa0SGreg Tucker w = rand() % MAX_ROLLING_HASH_WIDTH;
20853dc9fa0SGreg Tucker if (w < 3)
20953dc9fa0SGreg Tucker continue;
21053dc9fa0SGreg Tucker
21153dc9fa0SGreg Tucker mask = pick_rand_mask_in_range(4, 20);
21253dc9fa0SGreg Tucker trigger = rand() & mask;
21353dc9fa0SGreg Tucker p = buffer;
21453dc9fa0SGreg Tucker
21553dc9fa0SGreg Tucker // Function under test
21653dc9fa0SGreg Tucker FUT_init(&state, w);
21753dc9fa0SGreg Tucker FUT_reset(&state, p);
21877e513c6SMarcel Cornu FUT_run(&state, p + w, MAX_BUFFER_SIZE - w, mask, trigger, &offset_fut, &match);
21953dc9fa0SGreg Tucker offset_fut += w;
22053dc9fa0SGreg Tucker
22153dc9fa0SGreg Tucker // Reference
22253dc9fa0SGreg Tucker for (p++, offset = w + 1; offset < MAX_BUFFER_SIZE; offset++) {
22353dc9fa0SGreg Tucker hash = FUT_ref(&state, p++, w, 0);
22453dc9fa0SGreg Tucker if ((hash & mask) == trigger)
22553dc9fa0SGreg Tucker break;
22653dc9fa0SGreg Tucker }
22753dc9fa0SGreg Tucker
22853dc9fa0SGreg Tucker if (offset != offset_fut) {
22959ca9063SMarcel Cornu printf("\nrand case 2 #%d: w=%d, mask=0x%x, trigger=0x%x\n", r, w, mask,
23059ca9063SMarcel Cornu trigger);
23153dc9fa0SGreg Tucker printf(" offset of chunk different from ref\n");
23253dc9fa0SGreg Tucker printf(" case 2r: stop fut at offset=%d\n", offset_fut);
23353dc9fa0SGreg Tucker printf(" case 2r: stop ref at offset=%d\n", offset);
23453dc9fa0SGreg Tucker errors++;
2354c98a7e1SMarcel Cornu goto end;
23653dc9fa0SGreg Tucker }
23753dc9fa0SGreg Tucker putchar('.');
23853dc9fa0SGreg Tucker }
23953dc9fa0SGreg Tucker
24053dc9fa0SGreg Tucker // Test case 3, check if max bound is same
24153dc9fa0SGreg Tucker
24253dc9fa0SGreg Tucker w = 32;
24353dc9fa0SGreg Tucker mask = 0xfffff;
24453dc9fa0SGreg Tucker trigger = rand();
24553dc9fa0SGreg Tucker trigger &= mask;
24653dc9fa0SGreg Tucker putchar('|');
24753dc9fa0SGreg Tucker
24853dc9fa0SGreg Tucker for (max = w + 1; max < 500; max++) {
24953dc9fa0SGreg Tucker p = buffer;
25053dc9fa0SGreg Tucker FUT_init(&state, w);
25153dc9fa0SGreg Tucker FUT_reset(&state, p);
25253dc9fa0SGreg Tucker
25377e513c6SMarcel Cornu ret = FUT_run(&state, p + w, max - w, mask, trigger, &offset_fut, &match);
25477e513c6SMarcel Cornu
25577e513c6SMarcel Cornu if (ret != ISAL_CRYPTO_ERR_NONE) {
25677e513c6SMarcel Cornu printf(" %s (TC3) returned error %d\n", xstr(FUT_run), ret);
25777e513c6SMarcel Cornu errors++;
25877e513c6SMarcel Cornu }
25977e513c6SMarcel Cornu
26053dc9fa0SGreg Tucker offset_fut += w;
26153dc9fa0SGreg Tucker
2620200e16bSMarcel Cornu int ret_ref = ISAL_FINGERPRINT_RET_MAX;
26353dc9fa0SGreg Tucker for (p++, offset = w + 1; offset < max; offset++) {
26453dc9fa0SGreg Tucker hash = FUT_ref(&state, p++, w, 0);
26553dc9fa0SGreg Tucker if ((hash & mask) == trigger) {
2660200e16bSMarcel Cornu ret_ref = ISAL_FINGERPRINT_RET_HIT;
26753dc9fa0SGreg Tucker break;
26853dc9fa0SGreg Tucker }
26953dc9fa0SGreg Tucker }
27053dc9fa0SGreg Tucker
27177e513c6SMarcel Cornu if (offset != offset_fut || match != ret_ref) {
27253dc9fa0SGreg Tucker printf("\ncase 3 max=%d, offset of chunk different from ref\n", max);
27353dc9fa0SGreg Tucker printf(" case 3: stop fut at offset=%d\n", offset_fut);
27453dc9fa0SGreg Tucker printf(" case 3: stop ref at offset=%d\n", offset);
27577e513c6SMarcel Cornu printf(" case 3: ret_fut=%d ret_ref=%d\n", match, ret_ref);
27653dc9fa0SGreg Tucker errors++;
2774c98a7e1SMarcel Cornu goto end;
27853dc9fa0SGreg Tucker }
27953dc9fa0SGreg Tucker putchar('.'); // Finished test 3
28053dc9fa0SGreg Tucker }
28153dc9fa0SGreg Tucker
28253dc9fa0SGreg Tucker // Test case 4, check if max bound is same under random params
28353dc9fa0SGreg Tucker
28453dc9fa0SGreg Tucker for (r = 0; r < RANDOMS; r++) {
28553dc9fa0SGreg Tucker p = buffer;
28653dc9fa0SGreg Tucker mask = pick_rand_mask_in_range(24, 30); // Pick an unlikely mask
28753dc9fa0SGreg Tucker trigger = rand() & mask;
28853dc9fa0SGreg Tucker w = rand() % MAX_ROLLING_HASH_WIDTH;
28953dc9fa0SGreg Tucker max = rand() % 1024;
29053dc9fa0SGreg Tucker
29153dc9fa0SGreg Tucker if (w < 3 || max < 2 * MAX_ROLLING_HASH_WIDTH)
29253dc9fa0SGreg Tucker continue;
29353dc9fa0SGreg Tucker
29453dc9fa0SGreg Tucker FUT_init(&state, w);
29553dc9fa0SGreg Tucker FUT_reset(&state, p);
29653dc9fa0SGreg Tucker
29777e513c6SMarcel Cornu ret = FUT_run(&state, p, max, mask, trigger, &offset_fut, &match);
29877e513c6SMarcel Cornu
29977e513c6SMarcel Cornu if (ret != ISAL_CRYPTO_ERR_NONE) {
30077e513c6SMarcel Cornu printf(" %s (TC4) returned error %d\n", xstr(FUT_run), ret);
30177e513c6SMarcel Cornu errors++;
30277e513c6SMarcel Cornu }
30353dc9fa0SGreg Tucker
30453dc9fa0SGreg Tucker if (offset_fut <= w)
30553dc9fa0SGreg Tucker continue;
30653dc9fa0SGreg Tucker
3070200e16bSMarcel Cornu int ret_ref = ISAL_FINGERPRINT_RET_MAX;
30853dc9fa0SGreg Tucker for (p++, offset = w + 1; offset < max; offset++) {
30953dc9fa0SGreg Tucker hash = FUT_ref(&state, p++, w, 0);
31053dc9fa0SGreg Tucker if ((hash & mask) == trigger) {
3110200e16bSMarcel Cornu ret_ref = ISAL_FINGERPRINT_RET_HIT;
31253dc9fa0SGreg Tucker break;
31353dc9fa0SGreg Tucker }
31453dc9fa0SGreg Tucker }
31553dc9fa0SGreg Tucker
31677e513c6SMarcel Cornu if (offset != offset_fut || match != ret_ref) {
31753dc9fa0SGreg Tucker printf("\ncase 4 rand case different from ref, max=%d w=%d\n", max, w);
31853dc9fa0SGreg Tucker printf(" case 4: stop fut at offset=%d\n", offset_fut);
31953dc9fa0SGreg Tucker printf(" case 4: stop ref at offset=%d\n", offset);
32077e513c6SMarcel Cornu printf(" case 4: ret_fut=%d ret_ref=%d\n", match, ret_ref);
32153dc9fa0SGreg Tucker errors++;
3224c98a7e1SMarcel Cornu goto end;
32353dc9fa0SGreg Tucker }
32453dc9fa0SGreg Tucker putchar('.'); // Finished test 4
32553dc9fa0SGreg Tucker
3260200e16bSMarcel Cornu if (match == ISAL_FINGERPRINT_RET_HIT) {
32753dc9fa0SGreg Tucker p[-1] = rand(); // Keep hits from repeating
32853dc9fa0SGreg Tucker }
32953dc9fa0SGreg Tucker }
33053dc9fa0SGreg Tucker
3314c98a7e1SMarcel Cornu end:
3324c98a7e1SMarcel Cornu if (buffer != NULL)
3334c98a7e1SMarcel Cornu free(buffer);
3344c98a7e1SMarcel Cornu
33553dc9fa0SGreg Tucker if (errors > 0)
33653dc9fa0SGreg Tucker printf(" Fail: %d\n", errors);
33753dc9fa0SGreg Tucker else
33853dc9fa0SGreg Tucker printf(" Pass\n");
33953dc9fa0SGreg Tucker return errors;
3408c212bb2SPablo de Lara #else
3418c212bb2SPablo de Lara printf("FIPS Mode enabled. Test not run\n");
3428c212bb2SPablo de Lara
3438c212bb2SPablo de Lara return 0;
3448c212bb2SPablo de Lara #endif
34553dc9fa0SGreg Tucker }
346