1 /*
2  * Name hash functions
3  *
4  * Copyright (C) 2018-2021, 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 <memory.h>
24 #include <types.h>
25 
26 #include "libfsapfs_checksum.h"
27 #include "libfsapfs_libcerror.h"
28 #include "libfsapfs_libcnotify.h"
29 #include "libfsapfs_libuna.h"
30 #include "libfsapfs_name.h"
31 
32 libfsapfs_name_decomposition_mapping_t special_case_folding_000000df = { 2, { 0x00000073, 0x00000073 } };
33 libfsapfs_name_decomposition_mapping_t special_case_folding_00000130 = { 2, { 0x00000069, 0x00000307 } };
34 libfsapfs_name_decomposition_mapping_t special_case_folding_00000149 = { 2, { 0x000002bc, 0x0000006e } };
35 libfsapfs_name_decomposition_mapping_t special_case_folding_00000587 = { 2, { 0x00000565, 0x00000582 } };
36 libfsapfs_name_decomposition_mapping_t special_case_folding_00001e9a = { 2, { 0x00000061, 0x000002be } };
37 
38 libfsapfs_name_decomposition_mapping_t special_case_folding_00001f80[ 48 ] = {
39 	/* 00001f80 */ { 3, { 0x000003b1, 0x00000313, 0x000003b9 } },
40 	/* 00001f81 */ { 3, { 0x000003b1, 0x00000314, 0x000003b9 } },
41 	/* 00001f82 */ { 4, { 0x000003b1, 0x00000313, 0x00000300, 0x000003b9 } },
42 	/* 00001f83 */ { 4, { 0x000003b1, 0x00000314, 0x00000300, 0x000003b9 } },
43 	/* 00001f84 */ { 4, { 0x000003b1, 0x00000313, 0x00000301, 0x000003b9 } },
44 	/* 00001f85 */ { 4, { 0x000003b1, 0x00000314, 0x00000301, 0x000003b9 } },
45 	/* 00001f86 */ { 4, { 0x000003b1, 0x00000313, 0x00000342, 0x000003b9 } },
46 	/* 00001f87 */ { 4, { 0x000003b1, 0x00000314, 0x00000342, 0x000003b9 } },
47 	/* 00001f88 */ { 3, { 0x000003b1, 0x00000313, 0x000003b9 } },
48 	/* 00001f89 */ { 3, { 0x000003b1, 0x00000314, 0x000003b9 } },
49 	/* 00001f8a */ { 4, { 0x000003b1, 0x00000313, 0x00000300, 0x000003b9 } },
50 	/* 00001f8b */ { 4, { 0x000003b1, 0x00000314, 0x00000300, 0x000003b9 } },
51 	/* 00001f8c */ { 4, { 0x000003b1, 0x00000313, 0x00000301, 0x000003b9 } },
52 	/* 00001f8d */ { 4, { 0x000003b1, 0x00000314, 0x00000301, 0x000003b9 } },
53 	/* 00001f8e */ { 4, { 0x000003b1, 0x00000313, 0x00000342, 0x000003b9 } },
54 	/* 00001f8f */ { 4, { 0x000003b1, 0x00000314, 0x00000342, 0x000003b9 } },
55 	/* 00001f90 */ { 3, { 0x000003b7, 0x00000313, 0x000003b9 } },
56 	/* 00001f91 */ { 3, { 0x000003b7, 0x00000314, 0x000003b9 } },
57 	/* 00001f92 */ { 4, { 0x000003b7, 0x00000313, 0x00000300, 0x000003b9 } },
58 	/* 00001f93 */ { 4, { 0x000003b7, 0x00000314, 0x00000300, 0x000003b9 } },
59 	/* 00001f94 */ { 4, { 0x000003b7, 0x00000313, 0x00000301, 0x000003b9 } },
60 	/* 00001f95 */ { 4, { 0x000003b7, 0x00000314, 0x00000301, 0x000003b9 } },
61 	/* 00001f96 */ { 4, { 0x000003b7, 0x00000313, 0x00000342, 0x000003b9 } },
62 	/* 00001f97 */ { 4, { 0x000003b7, 0x00000314, 0x00000342, 0x000003b9 } },
63 	/* 00001f98 */ { 3, { 0x000003b7, 0x00000313, 0x000003b9 } },
64 	/* 00001f99 */ { 3, { 0x000003b7, 0x00000314, 0x000003b9 } },
65 	/* 00001f9a */ { 4, { 0x000003b7, 0x00000313, 0x00000300, 0x000003b9 } },
66 	/* 00001f9b */ { 4, { 0x000003b7, 0x00000314, 0x00000300, 0x000003b9 } },
67 	/* 00001f9c */ { 4, { 0x000003b7, 0x00000313, 0x00000301, 0x000003b9 } },
68 	/* 00001f9d */ { 4, { 0x000003b7, 0x00000314, 0x00000301, 0x000003b9 } },
69 	/* 00001f9e */ { 4, { 0x000003b7, 0x00000313, 0x00000342, 0x000003b9 } },
70 	/* 00001f9f */ { 4, { 0x000003b7, 0x00000314, 0x00000342, 0x000003b9 } },
71 	/* 00001fa0 */ { 3, { 0x000003c9, 0x00000313, 0x000003b9 } },
72 	/* 00001fa1 */ { 3, { 0x000003c9, 0x00000314, 0x000003b9 } },
73 	/* 00001fa2 */ { 4, { 0x000003c9, 0x00000313, 0x00000300, 0x000003b9 } },
74 	/* 00001fa3 */ { 4, { 0x000003c9, 0x00000314, 0x00000300, 0x000003b9 } },
75 	/* 00001fa4 */ { 4, { 0x000003c9, 0x00000313, 0x00000301, 0x000003b9 } },
76 	/* 00001fa5 */ { 4, { 0x000003c9, 0x00000314, 0x00000301, 0x000003b9 } },
77 	/* 00001fa6 */ { 4, { 0x000003c9, 0x00000313, 0x00000342, 0x000003b9 } },
78 	/* 00001fa7 */ { 4, { 0x000003c9, 0x00000314, 0x00000342, 0x000003b9 } },
79 	/* 00001fa8 */ { 3, { 0x000003c9, 0x00000313, 0x000003b9 } },
80 	/* 00001fa9 */ { 3, { 0x000003c9, 0x00000314, 0x000003b9 } },
81 	/* 00001faa */ { 4, { 0x000003c9, 0x00000313, 0x00000300, 0x000003b9 } },
82 	/* 00001fab */ { 4, { 0x000003c9, 0x00000314, 0x00000300, 0x000003b9 } },
83 	/* 00001fac */ { 4, { 0x000003c9, 0x00000313, 0x00000301, 0x000003b9 } },
84 	/* 00001fad */ { 4, { 0x000003c9, 0x00000314, 0x00000301, 0x000003b9 } },
85 	/* 00001fae */ { 4, { 0x000003c9, 0x00000313, 0x00000342, 0x000003b9 } },
86 	/* 00001faf */ { 4, { 0x000003c9, 0x00000314, 0x00000342, 0x000003b9 } }
87 };
88 
89 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb2 = { 3, { 0x000003b1, 0x00000300, 0x000003b9 } };
90 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb3 = { 2, { 0x000003b1, 0x000003b9 } };
91 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb4 = { 3, { 0x000003b1, 0x00000301, 0x000003b9 } };
92 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb6 = { 2, { 0x000003b1, 0x00000342 } };
93 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb7 = { 3, { 0x000003b1, 0x00000342, 0x000003b9 } };
94 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fbc = { 2, { 0x000003b1, 0x000003b9 } };
95 
96 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc2 = { 3, { 0x000003b7, 0x00000300, 0x000003b9 } };
97 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc3 = { 2, { 0x000003b7, 0x000003b9 } };
98 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc4 = { 3, { 0x000003b7, 0x00000301, 0x000003b9 } };
99 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc6 = { 2, { 0x000003b7, 0x00000342 } };
100 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc7 = { 3, { 0x000003b7, 0x00000342, 0x000003b9 } };
101 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fcc = { 2, { 0x000003b7, 0x000003b9 } };
102 
103 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff2 = { 3, { 0x000003c9, 0x00000300, 0x000003b9 } };
104 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff3 = { 2, { 0x000003c9, 0x000003b9 } };
105 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff4 = { 3, { 0x000003c9, 0x00000301, 0x000003b9 } };
106 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff6 = { 2, { 0x000003c9, 0x00000342 } };
107 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff7 = { 3, { 0x000003c9, 0x00000342, 0x000003b9 } };
108 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ffc = { 2, { 0x000003c9, 0x000003b9 } };
109 
110 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb00 = { 2, { 0x00000066, 0x00000066 } };
111 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb01 = { 2, { 0x00000066, 0x00000069 } };
112 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb02 = { 2, { 0x00000066, 0x0000006c } };
113 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb03 = { 3, { 0x00000066, 0x00000066, 0x00000069 } };
114 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb04 = { 3, { 0x00000066, 0x00000066, 0x0000006c } };
115 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb05 = { 2, { 0x00000073, 0x00000074 } };
116 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb06 = { 2, { 0x00000073, 0x00000074 } };
117 
118 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb13 = { 2, { 0x00000574, 0x00000576 } };
119 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb14 = { 2, { 0x00000574, 0x00000565 } };
120 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb15 = { 2, { 0x00000574, 0x0000056b } };
121 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb16 = { 2, { 0x0000057e, 0x00000576 } };
122 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb17 = { 2, { 0x00000574, 0x0000056d } };
123 
124 /* Calculates the name hash of an UTF-8 formatted string
125  * Returns 1 if successful or -1 on error
126  */
libfsapfs_name_hash_calculate_from_utf8_string(uint32_t * name_hash,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libcerror_error_t ** error)127 int libfsapfs_name_hash_calculate_from_utf8_string(
128      uint32_t *name_hash,
129      const uint8_t *utf8_string,
130      size_t utf8_string_length,
131      uint8_t use_case_folding,
132      libcerror_error_t **error )
133 {
134 	libfsapfs_name_decomposition_mapping_t single_nfd_mapping = { 1, { 0 } };
135 
136 	libfsapfs_name_decomposition_mapping_t *nfd_mapping       = NULL;
137 	static char *function                                     = "libfsapfs_name_hash_calculate_from_utf8_string";
138 	libuna_unicode_character_t unicode_character              = 0;
139 	size_t utf8_string_index                                  = 0;
140 	uint32_t calculated_checksum                              = 0;
141 	uint32_t checksum_table_index                             = 0;
142 	uint8_t byte_value                                        = 0;
143 	uint8_t nfd_character_index                               = 0;
144 
145 #if defined( HAVE_DEBUG_OUTPUT )
146 	uint8_t utf32_stream[ 512 ];
147 
148 	size_t utf32_stream_index                                 = 0;
149 #endif
150 
151 	if( name_hash == NULL )
152 	{
153 		libcerror_error_set(
154 		 error,
155 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
156 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
157 		 "%s: invalid name hash.",
158 		 function );
159 
160 		return( -1 );
161 	}
162 	if( libfsapfs_checksum_crc32_table_computed == 0 )
163 	{
164 		libfsapfs_checksum_initialize_crc32_table(
165 		 0x82f63b78UL );
166 	}
167 	calculated_checksum = 0xffffffffUL;
168 
169 	while( utf8_string_index < utf8_string_length )
170 	{
171 		if( libuna_unicode_character_copy_from_utf8(
172 		     &unicode_character,
173 		     utf8_string,
174 		     utf8_string_length,
175 		     &utf8_string_index,
176 		     error ) != 1 )
177 		{
178 			libcerror_error_set(
179 			 error,
180 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
181 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
182 			 "%s: unable to copy Unicode character from UTF-8 string.",
183 			 function );
184 
185 			return( -1 );
186 		}
187 		if( unicode_character == 0 )
188 		{
189 			break;
190 		}
191 		if( use_case_folding != 0 )
192 		{
193 			libfsapfs_name_get_case_folding_mapping(
194 			 unicode_character );
195 
196 			/* Overload the NFD mapping to handle special case folding
197 			 */
198 			if( ( unicode_character >= 0x00001f80UL )
199 			 && ( unicode_character <= 0x00001fafUL ) )
200 			{
201 				nfd_mapping = &( special_case_folding_00001f80[ unicode_character - 0x00001f80UL ] );
202 			}
203 			else switch( unicode_character )
204 			{
205 				case 0x000000dfUL:
206 					nfd_mapping = &special_case_folding_000000df;
207 					break;
208 
209 				case 0x00000130UL:
210 					nfd_mapping = &special_case_folding_00000130;
211 					break;
212 
213 				case 0x00000149UL:
214 					nfd_mapping = &special_case_folding_00000149;
215 					break;
216 
217 				case 0x00000587UL:
218 					nfd_mapping = &special_case_folding_00000587;
219 					break;
220 
221 				case 0x00001e9aUL:
222 					nfd_mapping = &special_case_folding_00001e9a;
223 					break;
224 
225 				case 0x00001fb2UL:
226 					nfd_mapping = &special_case_folding_00001fb2;
227 					break;
228 
229 				case 0x00001fb3UL:
230 					nfd_mapping = &special_case_folding_00001fb3;
231 					break;
232 
233 				case 0x00001fb4UL:
234 					nfd_mapping = &special_case_folding_00001fb4;
235 					break;
236 
237 				case 0x00001fb6UL:
238 					nfd_mapping = &special_case_folding_00001fb6;
239 					break;
240 
241 				case 0x00001fb7UL:
242 					nfd_mapping = &special_case_folding_00001fb7;
243 					break;
244 
245 				case 0x00001fbcUL:
246 					nfd_mapping = &special_case_folding_00001fbc;
247 					break;
248 
249 				case 0x00001fc2UL:
250 					nfd_mapping = &special_case_folding_00001fc2;
251 					break;
252 
253 				case 0x00001fc3UL:
254 					nfd_mapping = &special_case_folding_00001fc3;
255 					break;
256 
257 				case 0x00001fc4UL:
258 					nfd_mapping = &special_case_folding_00001fc4;
259 					break;
260 
261 				case 0x00001fc6UL:
262 					nfd_mapping = &special_case_folding_00001fc6;
263 					break;
264 
265 				case 0x00001fc7UL:
266 					nfd_mapping = &special_case_folding_00001fc7;
267 					break;
268 
269 				case 0x00001fccUL:
270 					nfd_mapping = &special_case_folding_00001fcc;
271 					break;
272 
273 				case 0x00001ff2UL:
274 					nfd_mapping = &special_case_folding_00001ff2;
275 					break;
276 
277 				case 0x00001ff3UL:
278 					nfd_mapping = &special_case_folding_00001ff3;
279 					break;
280 
281 				case 0x00001ff4UL:
282 					nfd_mapping = &special_case_folding_00001ff4;
283 					break;
284 
285 				case 0x00001ff6UL:
286 					nfd_mapping = &special_case_folding_00001ff6;
287 					break;
288 
289 				case 0x00001ff7UL:
290 					nfd_mapping = &special_case_folding_00001ff7;
291 					break;
292 
293 				case 0x00001ffcUL:
294 					nfd_mapping = &special_case_folding_00001ffc;
295 					break;
296 
297 				case 0x0000fb00UL:
298 					nfd_mapping = &special_case_folding_0000fb00;
299 					break;
300 
301 				case 0x0000fb01UL:
302 					nfd_mapping = &special_case_folding_0000fb01;
303 					break;
304 
305 				case 0x0000fb02UL:
306 					nfd_mapping = &special_case_folding_0000fb02;
307 					break;
308 
309 				case 0x0000fb03UL:
310 					nfd_mapping = &special_case_folding_0000fb03;
311 					break;
312 
313 				case 0x0000fb04UL:
314 					nfd_mapping = &special_case_folding_0000fb04;
315 					break;
316 
317 				case 0x0000fb05UL:
318 					nfd_mapping = &special_case_folding_0000fb05;
319 					break;
320 
321 				case 0x0000fb06UL:
322 					nfd_mapping = &special_case_folding_0000fb06;
323 					break;
324 
325 				case 0x0000fb13UL:
326 					nfd_mapping = &special_case_folding_0000fb13;
327 					break;
328 
329 				case 0x0000fb14UL:
330 					nfd_mapping = &special_case_folding_0000fb14;
331 					break;
332 
333 				case 0x0000fb15UL:
334 					nfd_mapping = &special_case_folding_0000fb15;
335 					break;
336 
337 				case 0x0000fb16UL:
338 					nfd_mapping = &special_case_folding_0000fb16;
339 					break;
340 
341 				case 0x0000fb17UL:
342 					nfd_mapping = &special_case_folding_0000fb17;
343 					break;
344 
345 				default:
346 					libfsapfs_name_get_decomposition_mapping(
347 					 unicode_character,
348 					 nfd_mapping,
349 					 single_nfd_mapping );
350 					break;
351 			}
352 		}
353 		else
354 		{
355 			libfsapfs_name_get_decomposition_mapping(
356 			 unicode_character,
357 			 nfd_mapping,
358 			 single_nfd_mapping );
359 		}
360 		for( nfd_character_index = 0;
361 		     nfd_character_index < nfd_mapping->number_of_characters;
362 		     nfd_character_index++ )
363 		{
364 			unicode_character = nfd_mapping->characters[ nfd_character_index ];
365 
366 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
367 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
368 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
369 			unicode_character  >>= 8;
370 
371 #if defined( HAVE_DEBUG_OUTPUT )
372 			if( utf32_stream_index < 512 )
373 			{
374 				utf32_stream[ utf32_stream_index++ ] = byte_value;
375 			}
376 #endif
377 
378 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
379 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
380 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
381 			unicode_character  >>= 8;
382 
383 #if defined( HAVE_DEBUG_OUTPUT )
384 			if( utf32_stream_index < 512 )
385 			{
386 				utf32_stream[ utf32_stream_index++ ] = byte_value;
387 			}
388 #endif
389 
390 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
391 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
392 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
393 			unicode_character  >>= 8;
394 
395 #if defined( HAVE_DEBUG_OUTPUT )
396 			if( utf32_stream_index < 512 )
397 			{
398 				utf32_stream[ utf32_stream_index++ ] = byte_value;
399 			}
400 #endif
401 
402 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
403 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
404 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
405 
406 #if defined( HAVE_DEBUG_OUTPUT )
407 			if( utf32_stream_index < 512 )
408 			{
409 				utf32_stream[ utf32_stream_index++ ] = byte_value;
410 			}
411 #endif
412 		}
413 	}
414 	*name_hash = calculated_checksum & 0x003fffffUL;
415 
416 #if defined( HAVE_DEBUG_OUTPUT )
417 	if( libcnotify_verbose != 0 )
418 	{
419 		libcnotify_printf(
420 		 "%s: UTF-32 stream data:\n",
421 		 function );
422 		libcnotify_print_data(
423 		 utf32_stream,
424 		 utf32_stream_index,
425 		 0 );
426 
427 		libcnotify_printf(
428 		 "%s: CRC-32 checkum\t\t: 0x%08" PRIx32 "\n",
429 		 function,
430 		 calculated_checksum );
431 
432 		libcnotify_printf(
433 		 "%s: name hash\t\t: 0x%06" PRIx32 "\n",
434 		 function,
435 		 *name_hash );
436 
437 		libcnotify_printf(
438 		 "\n" );
439 	}
440 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
441 
442 	return( 1 );
443 }
444 
445 /* Calculates the name hash of an UTF-16 formatted string
446  * Returns 1 if successful or -1 on error
447  */
libfsapfs_name_hash_calculate_from_utf16_string(uint32_t * name_hash,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libcerror_error_t ** error)448 int libfsapfs_name_hash_calculate_from_utf16_string(
449      uint32_t *name_hash,
450      const uint16_t *utf16_string,
451      size_t utf16_string_length,
452      uint8_t use_case_folding,
453      libcerror_error_t **error )
454 {
455 	libfsapfs_name_decomposition_mapping_t single_nfd_mapping = { 1, { 0 } };
456 
457 	libfsapfs_name_decomposition_mapping_t *nfd_mapping       = NULL;
458 	static char *function                                     = "libfsapfs_name_hash_calculate_from_utf16_string";
459 	libuna_unicode_character_t unicode_character              = 0;
460 	size_t utf16_string_index                                 = 0;
461 	uint32_t calculated_checksum                              = 0;
462 	uint32_t checksum_table_index                             = 0;
463 	uint8_t byte_value                                        = 0;
464 	uint8_t nfd_character_index                               = 0;
465 
466 #if defined( HAVE_DEBUG_OUTPUT )
467 	uint8_t utf32_stream[ 512 ];
468 
469 	size_t utf32_stream_index                                 = 0;
470 #endif
471 
472 	if( name_hash == NULL )
473 	{
474 		libcerror_error_set(
475 		 error,
476 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
477 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
478 		 "%s: invalid name hash.",
479 		 function );
480 
481 		return( -1 );
482 	}
483 	if( libfsapfs_checksum_crc32_table_computed == 0 )
484 	{
485 		libfsapfs_checksum_initialize_crc32_table(
486 		 0x82f63b78UL );
487 	}
488 	calculated_checksum = 0xffffffffUL;
489 
490 	while( utf16_string_index < utf16_string_length )
491 	{
492 		if( libuna_unicode_character_copy_from_utf16(
493 		     &unicode_character,
494 		     utf16_string,
495 		     utf16_string_length,
496 		     &utf16_string_index,
497 		     error ) != 1 )
498 		{
499 			libcerror_error_set(
500 			 error,
501 			 LIBCERROR_ERROR_DOMAIN_CONVERSION,
502 			 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
503 			 "%s: unable to copy Unicode character from UTF-16 string.",
504 			 function );
505 
506 			return( -1 );
507 		}
508 		if( unicode_character == 0 )
509 		{
510 			break;
511 		}
512 		if( use_case_folding != 0 )
513 		{
514 			libfsapfs_name_get_case_folding_mapping(
515 			 unicode_character );
516 
517 			/* Overload the NFD mapping to handle special case folding
518 			 */
519 			if( ( unicode_character >= 0x00001f80UL )
520 			 && ( unicode_character <= 0x00001fafUL ) )
521 			{
522 				nfd_mapping = &( special_case_folding_00001f80[ unicode_character - 0x00001f80UL ] );
523 			}
524 			else switch( unicode_character )
525 			{
526 				case 0x000000dfUL:
527 					nfd_mapping = &special_case_folding_000000df;
528 					break;
529 
530 				case 0x00000130UL:
531 					nfd_mapping = &special_case_folding_00000130;
532 					break;
533 
534 				case 0x00000149UL:
535 					nfd_mapping = &special_case_folding_00000149;
536 					break;
537 
538 				case 0x00000587UL:
539 					nfd_mapping = &special_case_folding_00000587;
540 					break;
541 
542 				case 0x00001e9aUL:
543 					nfd_mapping = &special_case_folding_00001e9a;
544 					break;
545 
546 				case 0x00001fb2UL:
547 					nfd_mapping = &special_case_folding_00001fb2;
548 					break;
549 
550 				case 0x00001fb3UL:
551 					nfd_mapping = &special_case_folding_00001fb3;
552 					break;
553 
554 				case 0x00001fb4UL:
555 					nfd_mapping = &special_case_folding_00001fb4;
556 					break;
557 
558 				case 0x00001fb6UL:
559 					nfd_mapping = &special_case_folding_00001fb6;
560 					break;
561 
562 				case 0x00001fb7UL:
563 					nfd_mapping = &special_case_folding_00001fb7;
564 					break;
565 
566 				case 0x00001fbcUL:
567 					nfd_mapping = &special_case_folding_00001fbc;
568 					break;
569 
570 				case 0x00001fc2UL:
571 					nfd_mapping = &special_case_folding_00001fc2;
572 					break;
573 
574 				case 0x00001fc3UL:
575 					nfd_mapping = &special_case_folding_00001fc3;
576 					break;
577 
578 				case 0x00001fc4UL:
579 					nfd_mapping = &special_case_folding_00001fc4;
580 					break;
581 
582 				case 0x00001fc6UL:
583 					nfd_mapping = &special_case_folding_00001fc6;
584 					break;
585 
586 				case 0x00001fc7UL:
587 					nfd_mapping = &special_case_folding_00001fc7;
588 					break;
589 
590 				case 0x00001fccUL:
591 					nfd_mapping = &special_case_folding_00001fcc;
592 					break;
593 
594 				case 0x00001ff2UL:
595 					nfd_mapping = &special_case_folding_00001ff2;
596 					break;
597 
598 				case 0x00001ff3UL:
599 					nfd_mapping = &special_case_folding_00001ff3;
600 					break;
601 
602 				case 0x00001ff4UL:
603 					nfd_mapping = &special_case_folding_00001ff4;
604 					break;
605 
606 				case 0x00001ff6UL:
607 					nfd_mapping = &special_case_folding_00001ff6;
608 					break;
609 
610 				case 0x00001ff7UL:
611 					nfd_mapping = &special_case_folding_00001ff7;
612 					break;
613 
614 				case 0x00001ffcUL:
615 					nfd_mapping = &special_case_folding_00001ffc;
616 					break;
617 
618 				case 0x0000fb00UL:
619 					nfd_mapping = &special_case_folding_0000fb00;
620 					break;
621 
622 				case 0x0000fb01UL:
623 					nfd_mapping = &special_case_folding_0000fb01;
624 					break;
625 
626 				case 0x0000fb02UL:
627 					nfd_mapping = &special_case_folding_0000fb02;
628 					break;
629 
630 				case 0x0000fb03UL:
631 					nfd_mapping = &special_case_folding_0000fb03;
632 					break;
633 
634 				case 0x0000fb04UL:
635 					nfd_mapping = &special_case_folding_0000fb04;
636 					break;
637 
638 				case 0x0000fb05UL:
639 					nfd_mapping = &special_case_folding_0000fb05;
640 					break;
641 
642 				case 0x0000fb06UL:
643 					nfd_mapping = &special_case_folding_0000fb06;
644 					break;
645 
646 				case 0x0000fb13UL:
647 					nfd_mapping = &special_case_folding_0000fb13;
648 					break;
649 
650 				case 0x0000fb14UL:
651 					nfd_mapping = &special_case_folding_0000fb14;
652 					break;
653 
654 				case 0x0000fb15UL:
655 					nfd_mapping = &special_case_folding_0000fb15;
656 					break;
657 
658 				case 0x0000fb16UL:
659 					nfd_mapping = &special_case_folding_0000fb16;
660 					break;
661 
662 				case 0x0000fb17UL:
663 					nfd_mapping = &special_case_folding_0000fb17;
664 					break;
665 
666 				default:
667 					libfsapfs_name_get_decomposition_mapping(
668 					 unicode_character,
669 					 nfd_mapping,
670 					 single_nfd_mapping );
671 					break;
672 			}
673 		}
674 		else
675 		{
676 			libfsapfs_name_get_decomposition_mapping(
677 			 unicode_character,
678 			 nfd_mapping,
679 			 single_nfd_mapping );
680 		}
681 		for( nfd_character_index = 0;
682 		     nfd_character_index < nfd_mapping->number_of_characters;
683 		     nfd_character_index++ )
684 		{
685 			unicode_character = nfd_mapping->characters[ nfd_character_index ];
686 
687 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
688 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
689 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
690 			unicode_character  >>= 8;
691 
692 #if defined( HAVE_DEBUG_OUTPUT )
693 			if( utf32_stream_index < 512 )
694 			{
695 				utf32_stream[ utf32_stream_index++ ] = byte_value;
696 			}
697 #endif
698 
699 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
700 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
701 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
702 			unicode_character  >>= 8;
703 
704 #if defined( HAVE_DEBUG_OUTPUT )
705 			if( utf32_stream_index < 512 )
706 			{
707 				utf32_stream[ utf32_stream_index++ ] = byte_value;
708 			}
709 #endif
710 
711 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
712 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
713 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
714 			unicode_character  >>= 8;
715 
716 #if defined( HAVE_DEBUG_OUTPUT )
717 			if( utf32_stream_index < 512 )
718 			{
719 				utf32_stream[ utf32_stream_index++ ] = byte_value;
720 			}
721 #endif
722 
723 			byte_value           = (uint8_t) ( unicode_character & 0x000000ffUL );
724 			checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
725 			calculated_checksum  = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
726 
727 #if defined( HAVE_DEBUG_OUTPUT )
728 			if( utf32_stream_index < 512 )
729 			{
730 				utf32_stream[ utf32_stream_index++ ] = byte_value;
731 			}
732 #endif
733 		}
734 	}
735 	*name_hash = calculated_checksum & 0x003fffffUL;
736 
737 #if defined( HAVE_DEBUG_OUTPUT )
738 	if( libcnotify_verbose != 0 )
739 	{
740 		libcnotify_printf(
741 		 "%s: UTF-32 stream data:\n",
742 		 function );
743 		libcnotify_print_data(
744 		 utf32_stream,
745 		 utf32_stream_index,
746 		 0 );
747 
748 		libcnotify_printf(
749 		 "%s: CRC-32 checkum\t\t: 0x%08" PRIx32 "\n",
750 		 function,
751 		 calculated_checksum );
752 
753 		libcnotify_printf(
754 		 "%s: name hash\t\t: 0x%06" PRIx32 "\n",
755 		 function,
756 		 *name_hash );
757 
758 		libcnotify_printf(
759 		 "\n" );
760 	}
761 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
762 
763 	return( 1 );
764 }
765 
766