diff options
Diffstat (limited to 'src/lib/util/crypto_crc.c')
-rw-r--r-- | src/lib/util/crypto_crc.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/lib/util/crypto_crc.c b/src/lib/util/crypto_crc.c new file mode 100644 index 000000000..f93b5b0b3 --- /dev/null +++ b/src/lib/util/crypto_crc.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001, 2002, 2003, 2004, 2006 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | |||
20 | For the actual CRC-32 code: | ||
21 | Copyright abandoned; this code is in the public domain. | ||
22 | Provided to GNUnet by peter@horizon.com | ||
23 | */ | ||
24 | |||
25 | /** | ||
26 | * @file util/crypto_crc.c | ||
27 | * @brief implementation of CRC16 and CRC32 | ||
28 | * @author Christian Grothoff | ||
29 | */ | ||
30 | |||
31 | #include "platform.h" | ||
32 | #include "gnunet_util_lib.h" | ||
33 | |||
34 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-crc", __VA_ARGS__) | ||
35 | |||
36 | /* Avoid wasting space on 8-byte longs. */ | ||
37 | #if UINT_MAX >= 0xffffffff | ||
38 | typedef unsigned int GNUNET_uLong; | ||
39 | #elif ULONG_MAX >= 0xffffffff | ||
40 | typedef unsigned long GNUNET_uLong; | ||
41 | #else | ||
42 | #error This compiler is not ANSI-compliant! | ||
43 | #endif | ||
44 | |||
45 | #define Z_NULL 0 | ||
46 | |||
47 | |||
48 | #define POLYNOMIAL (GNUNET_uLong) 0xedb88320 | ||
49 | static GNUNET_uLong crc_table[256]; | ||
50 | |||
51 | /* | ||
52 | * This routine writes each crc_table entry exactly once, | ||
53 | * with the correct final value. Thus, it is safe to call | ||
54 | * even on a table that someone else is using concurrently. | ||
55 | */ | ||
56 | static void | ||
57 | crc_init () | ||
58 | { | ||
59 | static int once; | ||
60 | GNUNET_uLong h = 1; | ||
61 | |||
62 | if (once) | ||
63 | return; | ||
64 | once = 1; | ||
65 | crc_table[0] = 0; | ||
66 | for (unsigned int i = 128; i; i >>= 1) | ||
67 | { | ||
68 | h = (h >> 1) ^ ((h & 1) ? POLYNOMIAL : 0); | ||
69 | /* h is now crc_table[i] */ | ||
70 | for (unsigned int j = 0; j < 256; j += 2 * i) | ||
71 | crc_table[i + j] = crc_table[j] ^ h; | ||
72 | } | ||
73 | } | ||
74 | |||
75 | |||
76 | /* | ||
77 | * This computes the standard preset and inverted CRC, as used | ||
78 | * by most networking standards. Start by passing in an initial | ||
79 | * chaining value of 0, and then pass in the return value from the | ||
80 | * previous crc32() call. The final return value is the CRC. | ||
81 | * Note that this is a little-endian CRC, which is best used with | ||
82 | * data transmitted lsbit-first, and it should, itself, be appended | ||
83 | * to data in little-endian byte and bit order to preserve the | ||
84 | * property of detecting all burst errors of length 32 bits or less. | ||
85 | */ | ||
86 | static GNUNET_uLong | ||
87 | gn_crc32 (GNUNET_uLong crc, const char *buf, size_t len) | ||
88 | { | ||
89 | crc_init (); | ||
90 | GNUNET_assert (crc_table[255] != 0); | ||
91 | crc ^= 0xffffffff; | ||
92 | while (len--) | ||
93 | crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; | ||
94 | return crc ^ 0xffffffff; | ||
95 | } | ||
96 | |||
97 | |||
98 | int32_t | ||
99 | GNUNET_CRYPTO_crc32_n (const void *buf, size_t len) | ||
100 | { | ||
101 | GNUNET_uLong crc; | ||
102 | |||
103 | crc = gn_crc32 (0L, Z_NULL, 0); | ||
104 | crc = gn_crc32 (crc, (char *) buf, len); | ||
105 | return crc; | ||
106 | } | ||
107 | |||
108 | |||
109 | uint32_t | ||
110 | GNUNET_CRYPTO_crc16_step (uint32_t sum, const void *buf, size_t len) | ||
111 | { | ||
112 | const uint16_t *hdr = buf; | ||
113 | |||
114 | for (; len >= 2; len -= 2) | ||
115 | sum += *(hdr++); | ||
116 | if (len == 1) | ||
117 | sum += ntohs(*((uint8_t *)hdr) << 8); | ||
118 | return sum; | ||
119 | } | ||
120 | |||
121 | |||
122 | uint16_t | ||
123 | GNUNET_CRYPTO_crc16_finish (uint32_t sum) | ||
124 | { | ||
125 | sum = (sum >> 16) + (sum & 0xFFFF); | ||
126 | sum += (sum >> 16); | ||
127 | |||
128 | return ~sum; | ||
129 | } | ||
130 | |||
131 | |||
132 | uint16_t | ||
133 | GNUNET_CRYPTO_crc16_n (const void *buf, size_t len) | ||
134 | { | ||
135 | const uint16_t *hdr = buf; | ||
136 | uint32_t sum = GNUNET_CRYPTO_crc16_step (0, hdr, len); | ||
137 | |||
138 | return GNUNET_CRYPTO_crc16_finish (sum); | ||
139 | } | ||
140 | |||
141 | |||
142 | /** | ||
143 | * @ingroup hash | ||
144 | * Calculate the checksum of a buffer in one step. | ||
145 | * | ||
146 | * @param buf buffer to calculate CRC over | ||
147 | * @param len number of bytes in @a buf | ||
148 | * @return crc8 value | ||
149 | */ | ||
150 | uint8_t | ||
151 | GNUNET_CRYPTO_crc8_n (const void *buf, | ||
152 | size_t len) | ||
153 | { | ||
154 | const uint8_t *data = buf; | ||
155 | unsigned int crc = 0; | ||
156 | int i; | ||
157 | int j; | ||
158 | |||
159 | for (j = len; 0 != j; j--) | ||
160 | { | ||
161 | crc ^= (*data++ << 8); | ||
162 | for (i = 8; 0 != i; i--) | ||
163 | { | ||
164 | if (0 != (crc & 0x8000)) | ||
165 | crc ^= (0x1070 << 3); | ||
166 | crc <<= 1; | ||
167 | } | ||
168 | } | ||
169 | return (uint8_t) (crc >> 8); | ||
170 | } | ||
171 | |||
172 | |||
173 | /* end of crypto_crc.c */ | ||