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/fs/fs.h>
9 #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
10 #include <zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_hash_checksum.h>
11 #include <string.h>
12 
13 #include <mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_config.h>
14 #include <mgmt/mcumgr/grp/fs_mgmt/fs_mgmt_hash_checksum_sha256.h>
15 
16 #ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT
17 #include <psa/crypto.h>
18 typedef psa_hash_operation_t hash_ctx_t;
19 #define SUCCESS_VALUE PSA_SUCCESS
20 
21 #else
22 #include <mbedtls/sha256.h>
23 typedef mbedtls_sha256_context hash_ctx_t;
24 #define SUCCESS_VALUE 0
25 
26 #endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */
27 
28 #define SHA256_DIGEST_SIZE 32
29 
30 /* The API that the different hash implementations provide further down. */
31 static int hash_setup(hash_ctx_t *);
32 static int hash_update(hash_ctx_t *, const uint8_t *input, size_t ilen);
33 static int hash_finish(hash_ctx_t *, uint8_t *output);
34 static void hash_teardown(hash_ctx_t *);
35 
fs_mgmt_hash_checksum_sha256(struct fs_file_t * file,uint8_t * output,size_t * out_len,size_t len)36 static int fs_mgmt_hash_checksum_sha256(struct fs_file_t *file, uint8_t *output,
37 					size_t *out_len, size_t len)
38 {
39 	int rc = MGMT_ERR_EUNKNOWN;
40 	ssize_t bytes_read = 0;
41 	size_t read_size = CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE;
42 	uint8_t buffer[CONFIG_MCUMGR_GRP_FS_CHECKSUM_HASH_CHUNK_SIZE];
43 	hash_ctx_t hash_ctx;
44 
45 	/* Clear variables prior to calculation */
46 	*out_len = 0;
47 	memset(output, 0, SHA256_DIGEST_SIZE);
48 
49 	if (hash_setup(&hash_ctx) != SUCCESS_VALUE) {
50 		goto teardown;
51 	}
52 
53 	/* Read all data from file and add to SHA256 hash calculation */
54 	do {
55 		if ((read_size + *out_len) >= len) {
56 			/* Limit read size to size of requested data */
57 			read_size = len - *out_len;
58 		}
59 
60 		bytes_read = fs_read(file, buffer, read_size);
61 
62 		if (bytes_read < 0) {
63 			/* Failed to read file data */
64 			goto teardown;
65 		} else if (bytes_read > 0) {
66 			if (hash_update(&hash_ctx, buffer, bytes_read) != SUCCESS_VALUE) {
67 				goto teardown;
68 			}
69 
70 			*out_len += bytes_read;
71 		}
72 	} while (bytes_read > 0 && *out_len < len);
73 
74 	/* Finalise SHA256 hash calculation and store output in provided output buffer */
75 	if (hash_finish(&hash_ctx, output) == SUCCESS_VALUE) {
76 		rc = 0;
77 	}
78 
79 teardown:
80 	hash_teardown(&hash_ctx);
81 
82 	return rc;
83 }
84 
85 static struct fs_mgmt_hash_checksum_group sha256 = {
86 	.group_name = "sha256",
87 	.byte_string = true,
88 	.output_size = SHA256_DIGEST_SIZE,
89 	.function = fs_mgmt_hash_checksum_sha256,
90 };
91 
fs_mgmt_hash_checksum_register_sha256(void)92 void fs_mgmt_hash_checksum_register_sha256(void)
93 {
94 	fs_mgmt_hash_checksum_register_group(&sha256);
95 }
96 
fs_mgmt_hash_checksum_unregister_sha256(void)97 void fs_mgmt_hash_checksum_unregister_sha256(void)
98 {
99 	fs_mgmt_hash_checksum_unregister_group(&sha256);
100 }
101 
102 #ifdef CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT
103 
hash_setup(psa_hash_operation_t * ctx)104 static int hash_setup(psa_hash_operation_t *ctx)
105 {
106 	*ctx = psa_hash_operation_init();
107 	return psa_hash_setup(ctx, PSA_ALG_SHA_256);
108 }
hash_update(psa_hash_operation_t * ctx,const uint8_t * input,size_t ilen)109 static int hash_update(psa_hash_operation_t *ctx, const uint8_t *input, size_t ilen)
110 {
111 	return psa_hash_update(ctx, input, ilen);
112 }
hash_finish(psa_hash_operation_t * ctx,uint8_t * output)113 static int hash_finish(psa_hash_operation_t *ctx, uint8_t *output)
114 {
115 	size_t output_length;
116 
117 	return psa_hash_finish(ctx, output, SHA256_DIGEST_SIZE, &output_length);
118 }
hash_teardown(psa_hash_operation_t * ctx)119 static void hash_teardown(psa_hash_operation_t *ctx)
120 {
121 	psa_hash_abort(ctx);
122 }
123 
124 #else
125 
hash_setup(mbedtls_sha256_context * ctx)126 static int hash_setup(mbedtls_sha256_context *ctx)
127 {
128 	mbedtls_sha256_init(ctx);
129 	return mbedtls_sha256_starts(ctx, false);
130 }
hash_update(mbedtls_sha256_context * ctx,const uint8_t * input,size_t ilen)131 static int hash_update(mbedtls_sha256_context *ctx, const uint8_t *input, size_t ilen)
132 {
133 	return mbedtls_sha256_update(ctx, input, ilen);
134 }
hash_finish(mbedtls_sha256_context * ctx,uint8_t * output)135 static int hash_finish(mbedtls_sha256_context *ctx, uint8_t *output)
136 {
137 	return mbedtls_sha256_finish(ctx, output);
138 }
hash_teardown(mbedtls_sha256_context * ctx)139 static void hash_teardown(mbedtls_sha256_context *ctx)
140 {
141 	mbedtls_sha256_free(ctx);
142 }
143 
144 #endif /* CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT */
145