Coverage Report

Created: 2025-06-13 07:21

/src/libpff/libpff/libpff_checksum.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Checksum functions
3
 *
4
 * Copyright (C) 2008-2024, 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 <types.h>
24
25
#include "libpff_libcerror.h"
26
27
/* Table of CRC-32 values of 8-bit values
28
 */
29
uint32_t libpff_checksum_crc32_table[ 256 ];
30
31
/* Value to indicate the CRC-32 table been computed
32
 */
33
int libpff_checksum_crc32_table_computed = 0;
34
35
/* Initializes the internal CRC-32 table
36
 * The table speeds up the CRC-32 calculation
37
 */
38
void libpff_checksum_initialize_crc32_table(
39
      uint32_t polynomial )
40
1
{
41
1
  uint32_t checksum    = 0;
42
1
  uint32_t table_index = 0;
43
1
  uint8_t bit_iterator = 0;
44
45
1
  for( table_index = 0;
46
257
       table_index < 256;
47
256
       table_index++ )
48
256
  {
49
256
    checksum = (uint32_t) table_index;
50
51
256
    for( bit_iterator = 0;
52
2.30k
         bit_iterator < 8;
53
2.04k
         bit_iterator++ )
54
2.04k
    {
55
2.04k
      if( checksum & 1 )
56
1.02k
      {
57
1.02k
        checksum = polynomial ^ ( checksum >> 1 );
58
1.02k
      }
59
1.02k
      else
60
1.02k
      {
61
1.02k
        checksum = checksum >> 1;
62
1.02k
      }
63
2.04k
    }
64
256
    libpff_checksum_crc32_table[ table_index ] = checksum;
65
256
  }
66
1
  libpff_checksum_crc32_table_computed = 1;
67
1
}
68
69
/* Calculates the CRC-32 checksum of a buffer
70
 * Returns 1 if successful or -1 on error
71
 */
72
int libpff_checksum_calculate_crc32(
73
     uint32_t *checksum,
74
     const uint8_t *buffer,
75
     size_t size,
76
     uint32_t initial_value,
77
     libcerror_error_t **error )
78
0
{
79
0
  static char *function  = "libpff_checksum_calculate_crc32";
80
0
  size_t buffer_offset   = 0;
81
0
  uint32_t safe_checksum = 0;
82
0
  uint32_t table_index   = 0;
83
84
0
  if( checksum == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
89
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
90
0
     "%s: invalid checksum.",
91
0
     function );
92
93
0
    return( -1 );
94
0
  }
95
0
  if( buffer == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
100
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
101
0
     "%s: invalid buffer.",
102
0
     function );
103
104
0
    return( -1 );
105
0
  }
106
0
  if( size > (size_t) SSIZE_MAX )
107
0
  {
108
0
    libcerror_error_set(
109
0
     error,
110
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
111
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
112
0
     "%s: invalid size value exceeds maximum.",
113
0
     function );
114
115
0
    return( -1 );
116
0
  }
117
0
        if( libpff_checksum_crc32_table_computed == 0 )
118
0
  {
119
0
    libpff_checksum_initialize_crc32_table(
120
0
     0xedb88320UL );
121
0
  }
122
0
  safe_checksum = initial_value ^ (uint32_t) 0xffffffffUL;
123
124
0
        for( buffer_offset = 0;
125
0
       buffer_offset < size;
126
0
       buffer_offset++ )
127
0
  {
128
0
    table_index = ( safe_checksum ^ buffer[ buffer_offset ] ) & 0x000000ffUL;
129
130
0
    safe_checksum = libpff_checksum_crc32_table[ table_index ] ^ ( safe_checksum >> 8 );
131
0
        }
132
0
        *checksum = safe_checksum ^ 0xffffffffUL;
133
134
0
  return( 1 );
135
0
}
136
137
/* Calculates the weak CRC-32 checksum of a buffer
138
 * Returns 1 if successful or -1 on error
139
 */
140
int libpff_checksum_calculate_weak_crc32(
141
     uint32_t *checksum,
142
     const uint8_t *buffer,
143
     size_t size,
144
     uint32_t initial_value,
145
     libcerror_error_t **error )
146
653k
{
147
653k
  static char *function  = "libpff_checksum_calculate_weak_crc32";
148
653k
  size_t buffer_offset   = 0;
149
653k
  uint32_t safe_checksum = 0;
150
653k
  uint32_t table_index   = 0;
151
152
653k
  if( checksum == NULL )
153
0
  {
154
0
    libcerror_error_set(
155
0
     error,
156
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
157
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
158
0
     "%s: invalid checksum.",
159
0
     function );
160
161
0
    return( -1 );
162
0
  }
163
653k
  if( buffer == NULL )
164
0
  {
165
0
    libcerror_error_set(
166
0
     error,
167
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
168
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
169
0
     "%s: invalid buffer.",
170
0
     function );
171
172
0
    return( -1 );
173
0
  }
174
653k
  if( size > (size_t) SSIZE_MAX )
175
0
  {
176
0
    libcerror_error_set(
177
0
     error,
178
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
179
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
180
0
     "%s: invalid size value exceeds maximum.",
181
0
     function );
182
183
0
    return( -1 );
184
0
  }
185
653k
        if( libpff_checksum_crc32_table_computed == 0 )
186
1
  {
187
1
    libpff_checksum_initialize_crc32_table(
188
1
     0xedb88320UL );
189
1
  }
190
653k
  safe_checksum = initial_value;
191
192
653k
        for( buffer_offset = 0;
193
329M
       buffer_offset < size;
194
328M
       buffer_offset++ )
195
328M
  {
196
328M
    table_index = ( safe_checksum ^ buffer[ buffer_offset ] ) & 0x000000ffUL;
197
198
328M
    safe_checksum = libpff_checksum_crc32_table[ table_index ] ^ ( safe_checksum >> 8 );
199
328M
        }
200
653k
  *checksum = safe_checksum;
201
202
653k
        return( 1 );
203
653k
}
204