1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Copyright (c) 2017-2019 Linaro LTD
5  * Copyright (c) 2017-2019 JUUL Labs
6  * Copyright (c) 2021-2023 Arm Limited
7  */
8 
9 /*
10  * This module provides a thin abstraction over some of the crypto
11  * primitives to make it easier to swap out the used crypto library.
12  *
13  * At this point, the choices are: MCUBOOT_USE_MBED_TLS, MCUBOOT_USE_TINYCRYPT,
14  * MCUBOOT_USE_PSA_CRYPTO, MCUBOOT_USE_CC310. Note that support for MCUBOOT_USE_PSA_CRYPTO
15  * is still experimental and it might not support all the crypto abstractions
16  * that MCUBOOT_USE_MBED_TLS supports. For this reason, it's allowed to have
17  * both of them defined, and for crypto modules that support both abstractions,
18  * the MCUBOOT_USE_PSA_CRYPTO will take precedence.
19  */
20 
21 #ifndef __BOOTUTIL_CRYPTO_SHA_H_
22 #define __BOOTUTIL_CRYPTO_SHA_H_
23 
24 #include "mcuboot_config/mcuboot_config.h"
25 #include "mcuboot_config/mcuboot_logging.h"
26 
27 #if defined(MCUBOOT_USE_PSA_CRYPTO) || defined(MCUBOOT_USE_MBED_TLS)
28 #define MCUBOOT_USE_PSA_OR_MBED_TLS
29 #endif /* MCUBOOT_USE_PSA_CRYPTO || MCUBOOT_USE_MBED_TLS */
30 
31 #if (defined(MCUBOOT_USE_PSA_OR_MBED_TLS) + \
32      defined(MCUBOOT_USE_TINYCRYPT) + \
33      defined(MCUBOOT_USE_CC310)) != 1
34     #error "One crypto backend must be defined: either CC310/MBED_TLS/TINYCRYPT/PSA_CRYPTO"
35 #endif
36 
37 #if defined(MCUBOOT_SHA512)
38     #define IMAGE_HASH_SIZE (64)
39     #define EXPECTED_HASH_TLV IMAGE_TLV_SHA512
40 #elif defined(MCUBOOT_SIGN_EC384)
41     #define IMAGE_HASH_SIZE (48)
42     #define EXPECTED_HASH_TLV IMAGE_TLV_SHA384
43 #else
44     #define IMAGE_HASH_SIZE (32)
45     #define EXPECTED_HASH_TLV IMAGE_TLV_SHA256
46 #endif /* MCUBOOT_SIGN */
47 
48 /* Universal defines for SHA-256 */
49 #define BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE  (64)
50 #define BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE (32)
51 
52 #if defined(MCUBOOT_USE_PSA_CRYPTO)
53 
54 #include <psa/crypto.h>
55 
56 #elif defined(MCUBOOT_USE_MBED_TLS)
57 
58 #ifdef MCUBOOT_SHA512
59 #include <mbedtls/sha512.h>
60 #else
61 #include <mbedtls/sha256.h>
62 #endif
63 
64 #include <mbedtls/version.h>
65 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
66 #include <mbedtls/compat-2.x.h>
67 #endif
68 
69 #endif /* MCUBOOT_USE_MBED_TLS */
70 
71 #if defined(MCUBOOT_USE_TINYCRYPT)
72 #if defined(MCUBOOT_SHA512)
73     #include <tinycrypt/sha512.h>
74 #else
75     #include <tinycrypt/sha256.h>
76 #endif
77     #include <tinycrypt/constants.h>
78 #endif /* MCUBOOT_USE_TINYCRYPT */
79 
80 #if defined(MCUBOOT_USE_CC310)
81     #include <cc310_glue.h>
82 #endif /* MCUBOOT_USE_CC310 */
83 
84 #include <stdint.h>
85 
86 #ifdef __cplusplus
87 extern "C" {
88 #endif
89 
90 #if defined(MCUBOOT_USE_PSA_CRYPTO)
91 
92 typedef psa_hash_operation_t bootutil_sha_context;
93 
bootutil_sha_init(bootutil_sha_context * ctx)94 static inline int bootutil_sha_init(bootutil_sha_context *ctx)
95 {
96     *ctx = psa_hash_operation_init();
97 #if defined(MCUBOOT_SHA512)
98     psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_512);
99 #elif defined(MCUBOOT_SIGN_EC384)
100     psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_384);
101 #else
102     psa_status_t status = psa_hash_setup(ctx, PSA_ALG_SHA_256);
103 #endif
104     return (int)status;
105 }
106 
bootutil_sha_drop(bootutil_sha_context * ctx)107 static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
108 {
109     return (int)psa_hash_abort(ctx);
110 }
111 
bootutil_sha_update(bootutil_sha_context * ctx,const void * data,uint32_t data_len)112 static inline int bootutil_sha_update(bootutil_sha_context *ctx,
113                                       const void *data,
114                                       uint32_t data_len)
115 {
116     return (int)psa_hash_update(ctx, data, data_len);
117 }
118 
bootutil_sha_finish(bootutil_sha_context * ctx,uint8_t * output)119 static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
120                                       uint8_t *output)
121 {
122     size_t hash_length = 0;
123     /* Assumes the output buffer is at least the expected size of the hash */
124 #if defined(MCUBOOT_SHA512)
125     return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_512), &hash_length);
126 #elif defined(MCUBOOT_SIGN_EC384)
127     return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_384), &hash_length);
128 #else
129     return (int)psa_hash_finish(ctx, output, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &hash_length);
130 #endif
131 }
132 
133 #elif defined(MCUBOOT_USE_MBED_TLS)
134 
135 #ifdef MCUBOOT_SHA512
136 typedef mbedtls_sha512_context bootutil_sha_context;
137 #else
138 typedef mbedtls_sha256_context bootutil_sha_context;
139 #endif
140 
141 static inline int bootutil_sha_init(bootutil_sha_context *ctx)
142 {
143     int ret;
144 
145 #ifdef MCUBOOT_SHA512
146     mbedtls_sha512_init(ctx);
147     ret = mbedtls_sha512_starts_ret(ctx, 0);
148 #else
149     mbedtls_sha256_init(ctx);
150     ret = mbedtls_sha256_starts_ret(ctx, 0);
151 #endif
152 
153     return ret;
154 }
155 
156 static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
157 {
158 #ifdef MCUBOOT_SHA512
159     mbedtls_sha512_free(ctx);
160 #else
161     mbedtls_sha256_free(ctx);
162 #endif
163 
164     return 0;
165 }
166 
167 static inline int bootutil_sha_update(bootutil_sha_context *ctx,
168                                       const void *data,
169                                       uint32_t data_len)
170 {
171     int ret;
172 
173 #ifdef MCUBOOT_SHA512
174     ret = mbedtls_sha512_update_ret(ctx, data, data_len);
175 #else
176     ret = mbedtls_sha256_update_ret(ctx, data, data_len);
177 #endif
178 
179     return ret;
180 }
181 
182 static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
183                                       uint8_t *output)
184 {
185     int ret;
186 
187 #ifdef MCUBOOT_SHA512
188     ret = mbedtls_sha512_finish_ret(ctx, output);
189 #else
190     ret = mbedtls_sha256_finish_ret(ctx, output);
191 #endif
192 
193     return ret;
194 }
195 
196 #endif /* MCUBOOT_USE_MBED_TLS */
197 
198 #if defined(MCUBOOT_USE_TINYCRYPT)
199 #if defined(MCUBOOT_SHA512)
200 typedef struct tc_sha512_state_struct bootutil_sha_context;
201 #else
202 typedef struct tc_sha256_state_struct bootutil_sha_context;
203 #endif
204 
bootutil_sha_init(bootutil_sha_context * ctx)205 static inline int bootutil_sha_init(bootutil_sha_context *ctx)
206 {
207 #if defined(MCUBOOT_SHA512)
208     tc_sha512_init(ctx);
209 #else
210     tc_sha256_init(ctx);
211 #endif
212     return 0;
213 }
214 
bootutil_sha_drop(bootutil_sha_context * ctx)215 static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
216 {
217     (void)ctx;
218     return 0;
219 }
220 
bootutil_sha_update(bootutil_sha_context * ctx,const void * data,uint32_t data_len)221 static inline int bootutil_sha_update(bootutil_sha_context *ctx,
222                                       const void *data,
223                                       uint32_t data_len)
224 {
225 #if defined(MCUBOOT_SHA512)
226     return tc_sha512_update(ctx, data, data_len);
227 #else
228     return tc_sha256_update(ctx, data, data_len);
229 #endif
230 }
231 
bootutil_sha_finish(bootutil_sha_context * ctx,uint8_t * output)232 static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
233                                       uint8_t *output)
234 {
235 #if defined(MCUBOOT_SHA512)
236     return tc_sha512_final(output, ctx);
237 #else
238     return tc_sha256_final(output, ctx);
239 #endif
240 }
241 #endif /* MCUBOOT_USE_TINYCRYPT */
242 
243 #if defined(MCUBOOT_USE_CC310)
bootutil_sha_init(bootutil_sha_context * ctx)244 static inline int bootutil_sha_init(bootutil_sha_context *ctx)
245 {
246     cc310_sha256_init(ctx);
247     return 0;
248 }
249 
bootutil_sha_drop(bootutil_sha_context * ctx)250 static inline int bootutil_sha_drop(bootutil_sha_context *ctx)
251 {
252     (void)ctx;
253     nrf_cc310_disable();
254     return 0;
255 }
256 
bootutil_sha_update(bootutil_sha_context * ctx,const void * data,uint32_t data_len)257 static inline int bootutil_sha_update(bootutil_sha_context *ctx,
258                                       const void *data,
259                                       uint32_t data_len)
260 {
261     cc310_sha256_update(ctx, data, data_len);
262     return 0;
263 }
264 
bootutil_sha_finish(bootutil_sha_context * ctx,uint8_t * output)265 static inline int bootutil_sha_finish(bootutil_sha_context *ctx,
266                                       uint8_t *output)
267 {
268     cc310_sha256_finalize(ctx, output);
269     return 0;
270 }
271 #endif /* MCUBOOT_USE_CC310 */
272 
273 #ifdef __cplusplus
274 }
275 #endif
276 
277 #endif /* __BOOTUTIL_CRYPTO_SHA_H_ */
278