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