Coverage Report

Created: 2025-10-13 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/p11-kit/common/hash.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2004, 2005, 2007, 2011  Internet Systems Consortium, Inc. ("ISC")
3
 * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4
 *
5
 * Permission to use, copy, modify, and/or distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
 * PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
/*! \file
19
 * SHA-1 in C
20
 * \author By Steve Reid <steve@edmweb.com>
21
 * 100% Public Domain
22
 * \verbatim
23
 * Test Vectors
24
 * "abc"
25
 *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
26
 * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
27
 *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
28
 * A million repetitions of "a"
29
 *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
30
 * \endverbatim
31
 */
32
33
#include "config.h"
34
35
#include "hash.h"
36
37
#include <assert.h>
38
#include <stdarg.h>
39
#include <stdint.h>
40
#include <string.h>
41
42
/* This code is based on the public domain MurmurHash3 from Austin Appleby:
43
 * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
44
 *
45
 * We use only the 32 bit variant, and slow it down a bit to support unaligned
46
 * reads.
47
 */
48
49
#if !defined(__cplusplus) && (__GNUC__ > 2)
50
#define GNUC_INLINE __attribute__((always_inline))
51
#else
52
#define GNUC_INLINE
53
#endif
54
55
GNUC_INLINE static inline uint32_t
56
rotl (uint32_t x,
57
      int8_t r)
58
0
{
59
0
  return (x << r) | (x >> (32 - r));
60
0
}
61
62
/*
63
 * Finalization mix - force all bits of a hash block to avalanche
64
 */
65
66
GNUC_INLINE static inline uint32_t
67
fmix (uint32_t h)
68
0
{
69
0
  h ^= h >> 16;
70
0
  h *= 0x85ebca6b;
71
0
  h ^= h >> 13;
72
0
  h *= 0xc2b2ae35;
73
0
  h ^= h >> 16;
74
75
0
  return h;
76
0
}
77
78
79
void
80
p11_hash_murmur3 (void *hash,
81
                  const void *input,
82
                  size_t len,
83
                  ...)
84
0
{
85
0
  uint8_t overflow[4];
86
0
  const uint8_t *data;
87
0
  va_list va;
88
0
  uint32_t h1;
89
0
  uint32_t k1;
90
0
  uint32_t c1;
91
0
  uint32_t c2;
92
93
0
  h1 = 42; /* arbitrary choice of seed */
94
0
  c1 = 0xcc9e2d51;
95
0
  c2 = 0x1b873593;
96
0
  data = input;
97
98
  /* body */
99
100
  /* Mix 4 bytes at a time into the hash */
101
0
  va_start (va, len);
102
0
  for (;;) {
103
0
    if (len >= 4) {
104
0
      memcpy (&k1, data, 4);
105
0
      data += 4;
106
0
      len -= 4;
107
108
0
    } else {
109
0
      size_t num = len;
110
0
      memcpy (overflow, data, len);
111
112
0
      while (num < 4) {
113
0
        size_t part;
114
115
0
        data = va_arg (va, const void *);
116
0
        if (!data)
117
0
          break;
118
119
        /* Combine uint32 from old and new */
120
0
        len = va_arg (va, size_t);
121
0
        part = 4 - num;
122
0
        if (part > len)
123
0
          part = len;
124
0
        memcpy (overflow + num, data, part);
125
0
        data += part;
126
0
        len -= part;
127
0
        num += part;
128
0
      }
129
130
0
      if (num < 4) {
131
0
        len = num;
132
0
        break;
133
0
      }
134
135
0
      memcpy (&k1, overflow, 4);
136
0
    }
137
138
0
    k1 *= c1;
139
0
    k1 = rotl (k1, 15);
140
0
    k1 *= c2;
141
142
0
    h1 ^= k1;
143
0
    h1 = rotl (h1, 13);
144
0
    h1 = h1 * 5 + 0xe6546b64;
145
0
  }
146
0
  va_end (va);
147
148
  /* tail */
149
150
0
  k1 = 0;
151
152
0
  switch (len) {
153
0
  case 3:
154
0
    k1 ^= overflow[2] << 16;
155
0
  case 2:
156
0
    k1 ^= overflow[1] << 8;
157
0
  case 1:
158
0
    k1 ^= overflow[0];
159
0
    k1 *= c1;
160
0
    k1 = rotl (k1, 15);
161
0
    k1 *= c2;
162
0
    h1 ^= k1;
163
0
  default:
164
0
    break;
165
0
  }
166
167
  /* finalization */
168
169
0
  h1 ^= len;
170
0
  h1 = fmix(h1);
171
172
0
  assert (sizeof (h1) == P11_HASH_MURMUR3_LEN);
173
0
  memcpy (hash, &h1, sizeof (h1));
174
0
}