1 /*
2 * Copyright (c) 2017-2021 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 * Copyright (c) 2017 Linaro Ltd
5 * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <errno.h>
11
12 #include <zephyr/types.h>
13 #include <stddef.h>
14 #include <string.h>
15 #include <sys/types.h>
16 #include <zephyr/device.h>
17 #include <zephyr/storage/flash_map.h>
18 #include "flash_map_priv.h"
19 #include <zephyr/drivers/flash.h>
20 #include <zephyr/init.h>
21
22 #define SHA256_DIGEST_SIZE 32
23 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
24 #include <psa/crypto.h>
25 #define SUCCESS_VALUE PSA_SUCCESS
26 #else
27 #include <mbedtls/sha256.h>
28 #define SUCCESS_VALUE 0
29 #endif
30
flash_area_check_int_sha256(const struct flash_area * fa,const struct flash_area_check * fac)31 int flash_area_check_int_sha256(const struct flash_area *fa,
32 const struct flash_area_check *fac)
33 {
34 unsigned char hash[SHA256_DIGEST_SIZE];
35 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
36 psa_hash_operation_t hash_ctx;
37 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
38 mbedtls_sha256_context hash_ctx;
39 #endif
40 int to_read;
41 int pos;
42 int rc;
43
44 if (fa == NULL || fac == NULL || fac->match == NULL ||
45 fac->rbuf == NULL || fac->clen == 0 || fac->rblen == 0) {
46 return -EINVAL;
47 }
48
49 if (!is_in_flash_area_bounds(fa, fac->off, fac->clen)) {
50 return -EINVAL;
51 }
52
53 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
54 hash_ctx = psa_hash_operation_init();
55 rc = psa_hash_setup(&hash_ctx, PSA_ALG_SHA_256);
56 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
57 mbedtls_sha256_init(&hash_ctx);
58 rc = mbedtls_sha256_starts(&hash_ctx, false);
59 #endif
60 if (rc != SUCCESS_VALUE) {
61 return -ESRCH;
62 }
63
64 to_read = fac->rblen;
65
66 for (pos = 0; pos < fac->clen; pos += to_read) {
67 if (pos + to_read > fac->clen) {
68 to_read = fac->clen - pos;
69 }
70
71 rc = flash_read(fa->fa_dev, (fa->fa_off + fac->off + pos),
72 fac->rbuf, to_read);
73 if (rc != 0) {
74 goto error;
75 }
76
77 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
78 rc = psa_hash_update(&hash_ctx, fac->rbuf, to_read);
79 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
80 rc = mbedtls_sha256_update(&hash_ctx, fac->rbuf, to_read);
81 #endif
82 if (rc != SUCCESS_VALUE) {
83 rc = -ESRCH;
84 goto error;
85 }
86 }
87
88 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
89 size_t hash_len;
90
91 rc = psa_hash_finish(&hash_ctx, hash, sizeof(hash), &hash_len);
92 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
93 rc = mbedtls_sha256_finish(&hash_ctx, hash);
94 #endif
95 if (rc != SUCCESS_VALUE) {
96 rc = -ESRCH;
97 goto error;
98 }
99
100 if (memcmp(hash, fac->match, SHA256_DIGEST_SIZE)) {
101 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
102 /* The operation has already been terminated. */
103 return -EILSEQ;
104 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
105 rc = -EILSEQ;
106 goto error;
107 #endif
108 }
109
110 error:
111 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA)
112 psa_hash_abort(&hash_ctx);
113 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
114 mbedtls_sha256_free(&hash_ctx);
115 #endif
116 return rc;
117 }
118