Coverage Report

Created: 2023-06-07 06:53

/src/libfsapfs/libfsapfs/libfsapfs_checksum.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Checksum functions
3
 *
4
 * Copyright (C) 2018-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <types.h>
25
26
#include "libfsapfs_libcerror.h"
27
28
/* Table of CRC-32 values of 8-bit values
29
 */
30
uint32_t libfsapfs_checksum_crc32_table[ 256 ];
31
32
/* Value to indicate the CRC-32 table been computed
33
 */
34
int libfsapfs_checksum_crc32_table_computed = 0;
35
36
/* Initializes the internal CRC-32 table
37
 * The table speeds up the CRC-32 calculation
38
 */
39
void libfsapfs_checksum_initialize_crc32_table(
40
      uint32_t polynomial )
41
0
{
42
0
  uint32_t checksum    = 0;
43
0
  uint32_t table_index = 0;
44
0
  uint8_t bit_iterator = 0;
45
46
0
  for( table_index = 0;
47
0
       table_index < 256;
48
0
       table_index++ )
49
0
  {
50
0
    checksum = (uint32_t) table_index;
51
52
0
    for( bit_iterator = 0;
53
0
         bit_iterator < 8;
54
0
         bit_iterator++ )
55
0
    {
56
0
      if( checksum & 1 )
57
0
      {
58
0
        checksum = polynomial ^ ( checksum >> 1 );
59
0
      }
60
0
      else
61
0
      {
62
0
        checksum = checksum >> 1;
63
0
      }
64
0
    }
65
0
    libfsapfs_checksum_crc32_table[ table_index ] = checksum;
66
0
  }
67
0
  libfsapfs_checksum_crc32_table_computed = 1;
68
0
}
69
70
/* Calculates the weak CRC-32 checksum of a buffer of data
71
 * Returns 1 if successful or -1 on error
72
 */
73
int libfsapfs_checksum_calculate_weak_crc32(
74
     uint32_t *checksum,
75
     const uint8_t *buffer,
76
     size_t size,
77
     uint32_t initial_value,
78
     libcerror_error_t **error )
79
0
{
80
0
  static char *function  = "libfsapfs_checkcum_calculate_weak_crc32";
81
0
  size_t buffer_offset   = 0;
82
0
  uint32_t safe_checksum = 0;
83
0
  uint32_t table_index   = 0;
84
85
0
  if( checksum == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
90
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
91
0
     "%s: invalid checksum.",
92
0
     function );
93
94
0
    return( -1 );
95
0
  }
96
0
  if( buffer == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
101
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
102
0
     "%s: invalid buffer.",
103
0
     function );
104
105
0
    return( -1 );
106
0
  }
107
0
  if( size > (size_t) SSIZE_MAX )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
112
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
113
0
     "%s: invalid size value exceeds maximum.",
114
0
     function );
115
116
0
    return( -1 );
117
0
  }
118
0
        if( libfsapfs_checksum_crc32_table_computed == 0 )
119
0
  {
120
0
    libfsapfs_checksum_initialize_crc32_table(
121
0
     0x82f63b78UL );
122
0
  }
123
0
  safe_checksum = initial_value;
124
125
0
        for( buffer_offset = 0;
126
0
       buffer_offset < size;
127
0
       buffer_offset++ )
128
0
  {
129
0
    table_index = ( safe_checksum ^ buffer[ buffer_offset ] ) & 0x000000ffUL;
130
131
0
    safe_checksum = libfsapfs_checksum_crc32_table[ table_index ] ^ ( safe_checksum >> 8 );
132
0
        }
133
0
  *checksum = safe_checksum;
134
135
0
  return( 1 );
136
0
}
137
138
/* Calculates the Fletcher-64 of a buffer of data
139
 * Returns 1 if successful or -1 on error
140
 */
141
int libfsapfs_checksum_calculate_fletcher64(
142
     uint64_t *checksum,
143
     const uint8_t *buffer,
144
     size_t size,
145
     uint64_t initial_value,
146
     libcerror_error_t **error )
147
12.0k
{
148
12.0k
  static char *function = "libfsapfs_checksum_calculate_fletcher64";
149
12.0k
  size_t buffer_offset  = 0;
150
12.0k
  uint64_t lower_32bit  = 0;
151
12.0k
  uint64_t upper_32bit  = 0;
152
12.0k
  uint32_t value_32bit  = 0;
153
154
12.0k
  if( buffer == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid buffer.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
12.0k
  if( size > (size_t) SSIZE_MAX )
166
0
  {
167
0
    libcerror_error_set(
168
0
     error,
169
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
171
0
     "%s: invalid size value exceeds maximum.",
172
0
     function );
173
174
0
    return( -1 );
175
0
  }
176
12.0k
  if( ( size % 4 ) != 0 )
177
0
  {
178
0
    libcerror_error_set(
179
0
     error,
180
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
181
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
182
0
     "%s: invalid size value out of bounds.",
183
0
     function );
184
185
0
    return( -1 );
186
0
  }
187
12.0k
  if( checksum == NULL )
188
0
  {
189
0
    libcerror_error_set(
190
0
     error,
191
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
192
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
193
0
     "%s: invalid checksum.",
194
0
     function );
195
196
0
    return( -1 );
197
0
  }
198
12.0k
  lower_32bit = initial_value & 0xffffffffUL;
199
12.0k
  upper_32bit = ( initial_value >> 32 ) & 0xffffffffUL;
200
201
12.0k
        for( buffer_offset = 0;
202
12.3M
       buffer_offset < size;
203
12.3M
       buffer_offset += 4 )
204
12.3M
  {
205
12.3M
    byte_stream_copy_to_uint32_little_endian(
206
12.3M
     &( buffer[ buffer_offset ] ),
207
12.3M
     value_32bit );
208
209
12.3M
    lower_32bit += value_32bit;
210
12.3M
    upper_32bit += lower_32bit;
211
12.3M
  }
212
12.0k
  lower_32bit %= 0xffffffffUL;
213
12.0k
  upper_32bit %= 0xffffffffUL;
214
215
12.0k
  value_32bit = 0xffffffffUL - ( ( lower_32bit + upper_32bit ) % 0xffffffffUL );
216
12.0k
  upper_32bit = 0xffffffffUL - ( ( lower_32bit + value_32bit ) % 0xffffffffUL );
217
218
12.0k
  *checksum = ( upper_32bit << 32 ) | value_32bit;
219
220
12.0k
  return( 1 );
221
12.0k
}
222