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