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 <sys/types.h>
15 #include <zephyr/device.h>
16 #include <zephyr/storage/flash_map.h>
17 #include "flash_map_priv.h"
18 #include <zephyr/drivers/flash.h>
19 #include <zephyr/init.h>
20 
21 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY)
22 #define SHA256_DIGEST_SIZE 32
23 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
24 #include <tinycrypt/constants.h>
25 #include <tinycrypt/sha256.h>
26 #else
27 #include <mbedtls/md.h>
28 #endif
29 #include <string.h>
30 #endif /* CONFIG_FLASH_AREA_CHECK_INTEGRITY */
31 
flash_area_check_int_sha256(const struct flash_area * fa,const struct flash_area_check * fac)32 int flash_area_check_int_sha256(const struct flash_area *fa,
33 				const struct flash_area_check *fac)
34 {
35 	unsigned char hash[SHA256_DIGEST_SIZE];
36 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
37 	struct tc_sha256_state_struct sha;
38 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
39 	mbedtls_md_context_t mbed_hash_ctx;
40 	const mbedtls_md_info_t *mbed_hash_info;
41 #endif
42 	int to_read;
43 	int pos;
44 	int rc;
45 
46 	if (fa == NULL || fac == NULL || fac->match == NULL ||
47 	    fac->rbuf == NULL || fac->clen == 0 || fac->rblen == 0) {
48 		return -EINVAL;
49 	}
50 
51 	if (!is_in_flash_area_bounds(fa, fac->off, fac->clen)) {
52 		return -EINVAL;
53 	}
54 
55 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
56 	if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) {
57 		return -ESRCH;
58 	}
59 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
60 	mbed_hash_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
61 
62 	mbedtls_md_init(&mbed_hash_ctx);
63 
64 	if (mbedtls_md_setup(&mbed_hash_ctx, mbed_hash_info, 0) != 0) {
65 		return -ESRCH;
66 	}
67 
68 	if (mbedtls_md_starts(&mbed_hash_ctx)) {
69 		rc = -ESRCH;
70 		goto error;
71 	}
72 #endif
73 
74 	to_read = fac->rblen;
75 
76 	for (pos = 0; pos < fac->clen; pos += to_read) {
77 		if (pos + to_read > fac->clen) {
78 			to_read = fac->clen - pos;
79 		}
80 
81 		rc = flash_read(fa->fa_dev, (fa->fa_off + fac->off + pos),
82 				fac->rbuf, to_read);
83 		if (rc != 0) {
84 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
85 			return rc;
86 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
87 			goto error;
88 #endif
89 		}
90 
91 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
92 		if (tc_sha256_update(&sha,
93 				     fac->rbuf,
94 				     to_read) != TC_CRYPTO_SUCCESS) {
95 			return -ESRCH;
96 		}
97 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
98 		if (mbedtls_md_update(&mbed_hash_ctx, fac->rbuf, to_read) != 0) {
99 			rc = -ESRCH;
100 			goto error;
101 		}
102 #endif
103 	}
104 
105 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
106 	if (tc_sha256_final(hash, &sha) != TC_CRYPTO_SUCCESS) {
107 		return -ESRCH;
108 	}
109 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
110 	if (mbedtls_md_finish(&mbed_hash_ctx, hash) != 0) {
111 		rc = -ESRCH;
112 		goto error;
113 	}
114 #endif
115 
116 	if (memcmp(hash, fac->match, SHA256_DIGEST_SIZE)) {
117 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_TC)
118 		return -EILSEQ;
119 #else /* CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS */
120 		rc = -EILSEQ;
121 		goto error;
122 #endif
123 	}
124 
125 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY_MBEDTLS)
126 error:
127 	mbedtls_md_free(&mbed_hash_ctx);
128 #endif
129 	return rc;
130 }
131