1 /*
2  * Copyright (c) 2022 Laird Connectivity
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/crc.h>
9 #include <zephyr/fs/fs.h>
10 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
11 #include <zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_hash_checksum.h>
12 #include <string.h>
13 
14 #include <mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_config.h>
15 #include <mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_hash_checksum_crc32.h>
16 
17 #define CRC32_SIZE 4
18 
fs_mgmt_hash_checksum_crc32(struct fs_file_t * file,uint8_t * output,size_t * out_len,size_t len)19 static int fs_mgmt_hash_checksum_crc32(struct fs_file_t *file, uint8_t *output,
20 				       size_t *out_len, size_t len)
21 {
22 	/* Calculate IEEE CRC32 checksum of target file */
23 	uint8_t buffer[CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE];
24 	ssize_t bytes_read = 0;
25 	size_t read_size = CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE;
26 	uint32_t crc32 = 0;
27 
28 	/* Clear length prior to calculation */
29 	*out_len = 0;
30 
31 	do {
32 		if ((read_size + *out_len) >= len) {
33 			/* Limit read size to size of requested data */
34 			read_size = len - *out_len;
35 		}
36 
37 		bytes_read = fs_read(file, buffer, read_size);
38 
39 		if (bytes_read < 0) {
40 			/* Failed to read file data, pass generic unknown error back */
41 			return MGMT_ERR_EUNKNOWN;
42 		} else if (bytes_read > 0) {
43 			crc32 = crc32_ieee_update(crc32, buffer, bytes_read);
44 			*out_len += bytes_read;
45 		}
46 	} while (bytes_read > 0 && *out_len < len);
47 
48 	memcpy(output, &crc32, sizeof(crc32));
49 
50 	return 0;
51 }
52 
53 static struct fs_mgmt_hash_checksum_group crc32 = {
54 	.group_name = "crc32",
55 	.byte_string = false,
56 	.output_size = CRC32_SIZE,
57 	.function = fs_mgmt_hash_checksum_crc32,
58 };
59 
fs_mgmt_hash_checksum_register_crc32(void)60 void fs_mgmt_hash_checksum_register_crc32(void)
61 {
62 	fs_mgmt_hash_checksum_register_group(&crc32);
63 }
64 
fs_mgmt_hash_checksum_unregister_crc32(void)65 void fs_mgmt_hash_checksum_unregister_crc32(void)
66 {
67 	fs_mgmt_hash_checksum_unregister_group(&crc32);
68 }
69