2828const uint8_t LEAF_PREFIX = 0x00 ;
2929const uint8_t INNER_PREFIX = 0x01 ;
3030
31+ static parser_error_t check_range_proof_inner (proof_t * proof , uint32_t start_index , uint32_t subtrie_size , uint32_t offset );
32+
3133/**
3234 * @brief Calculate the largest power of two which is strictly less than the argument.
3335 *
3436 * @param n The input value.
3537 * @return The largest power of two which is strictly less than the argument.
3638 */
3739static uint32_t next_smaller_po2 (uint32_t n ) {
40+ if (n == 0 ) {
41+ return 0 ;
42+ }
43+
3844 if ((n & (n - 1 )) == 0 ) {
3945 return n >> 1 ;
4046 }
@@ -44,6 +50,11 @@ static uint32_t next_smaller_po2(uint32_t n) {
4450 n |= n >> 4 ;
4551 n |= n >> 8 ;
4652 n |= n >> 16 ;
53+
54+ if (n == UINT32_MAX ) {
55+ return (UINT32_MAX >> 1 ) + 1 ;
56+ }
57+
4758 n += 1 ;
4859
4960 // Return the next smaller power of two
@@ -85,6 +96,9 @@ parser_error_t compute_tree_size(uint32_t num_right_siblings, uint32_t index_of_
8596
8697 while (remaining_right_siblings > 0 ) {
8798 if ((index_of_final_node & mask ) == 0 ) {
99+ if (index_of_final_node > UINT32_MAX - mask ) {
100+ return parser_value_out_of_range ;
101+ }
88102 index_of_final_node |= mask ;
89103 remaining_right_siblings -- ;
90104 }
@@ -128,6 +142,10 @@ static parser_error_t hash_leaf(proof_t *proof) {
128142// Declaring array sizes as static will trigger a warning if the user pass an array smaller than the size
129143static parser_error_t merge_branches (const uint8_t left [CX_SHA256_SIZE ], const uint8_t right [CX_SHA256_SIZE ],
130144 uint8_t output [CX_SHA256_SIZE ]) {
145+ CHECK_INPUT (left );
146+ CHECK_INPUT (right );
147+ CHECK_INPUT (output );
148+
131149 bytes_t buffer_left = {0 };
132150 buffer_left .ptr = left ;
133151 buffer_left .len = CX_SHA256_SIZE ;
@@ -151,82 +169,87 @@ static parser_error_t merge_branches(const uint8_t left[CX_SHA256_SIZE], const u
151169 return parser_ok ;
152170}
153171
172+ /**
173+ * @brief Get the subtree hash.
174+ *
175+ * @param proof The proof structure containing the necessary data.
176+ * @param start_index The start index.
177+ * @param subtrie_size The subtrie size.
178+ * @param offset The offset.
179+ * @param hash The output buffer for the hash.
180+ * @return parser_error_t Error code indicating the result of the operation.
181+ */
182+ static parser_error_t get_subtree_hash (proof_t * proof , uint32_t start_index , uint32_t subtrie_size , uint32_t offset ,
183+ const uint8_t * * hash ) {
184+ CHECK_INPUT (proof );
185+ CHECK_INPUT (proof -> hash );
186+ CHECK_INPUT (hash );
187+
188+ if (subtrie_size == 1 ) {
189+ * hash = proof -> hash ;
190+ } else {
191+ CHECK_ERROR (check_range_proof_inner (proof , start_index , subtrie_size , offset ));
192+ * hash = proof -> hash ;
193+ }
194+ return parser_ok ;
195+ }
196+
197+ /**
198+ * @brief Get the lemma hash.
199+ *
200+ * @param proof The proof structure containing the necessary data.
201+ * @param hash The output buffer for the hash.
202+ * @return parser_error_t Error code indicating the result of the operation.
203+ */
204+ static parser_error_t get_lemma_hash (proof_t * proof , const uint8_t * * hash ) {
205+ CHECK_INPUT (proof );
206+ CHECK_INPUT (hash );
207+
208+ if (proof -> lemma_index < 0 ) {
209+ return parser_value_out_of_range ;
210+ }
211+ uint32_t offset = CX_SHA256_SIZE * proof -> lemma_index ;
212+ if (offset >= proof -> lemmas .data .buffer .len ) {
213+ return parser_value_out_of_range ;
214+ }
215+ * hash = proof -> lemmas .data .buffer .ptr + offset ;
216+ proof -> lemma_index -- ;
217+ return parser_ok ;
218+ }
219+
220+ /**
221+ * @brief Recursively check the range proof inner to merge the branches of the proof.
222+ *
223+ * @param proof The proof structure containing the necessary data.
224+ * @param start_index The start index.
225+ * @param subtrie_size The subtrie size.
226+ * @param offset The offset.
227+ * @return parser_error_t Error code indicating the result of the operation.
228+ */
154229static parser_error_t check_range_proof_inner (proof_t * proof , uint32_t start_index , uint32_t subtrie_size , uint32_t offset ) {
155230 CHECK_INPUT (proof );
156231
157232 uint32_t split_index = next_smaller_po2 (subtrie_size );
158- print_u32 ("split_point:" , split_index );
159-
160233 uint32_t leaves_end_idx = (proof -> indices .entries + start_index ) - 1 ;
161- print_u32 ("leaves_end_idx:" , leaves_end_idx );
162-
163- // TODO: remove this
164- bytes_t buffer_left = {0 };
165- bytes_t buffer_right = {0 };
166234
167235 // Check right subtree
168236 const uint8_t * right ;
169237 if (leaves_end_idx >= (split_index + offset )) {
170238 uint32_t right_subtrie_size = subtrie_size - split_index ;
171- if (right_subtrie_size == 1 ) {
172- right = proof -> hash ;
173-
174- buffer_right .ptr = right ;
175- buffer_right .len = CX_SHA256_SIZE ;
176- print_buffer (& buffer_right , "right inside if true" );
177- } else {
178- print_u32 ("right inside else:" , right_subtrie_size );
179- CHECK_ERROR (check_range_proof_inner (proof , start_index , right_subtrie_size , offset + split_index ));
180- right = proof -> hash ;
181- }
239+ CHECK_ERROR (get_subtree_hash (proof , start_index , right_subtrie_size , offset + split_index , & right ));
182240 } else {
183- if (proof -> lemmas_ctx .last_index < 0 ) {
184- return parser_value_out_of_range ;
185- }
186- right = proof -> lemmas_ctx .lemmas .data .buffer .ptr + CX_SHA256_SIZE * proof -> lemmas_ctx .last_index ;
187- proof -> lemmas_ctx .last_index -- ;
188-
189- buffer_right .ptr = right ;
190- buffer_right .len = CX_SHA256_SIZE ;
191- print_buffer (& buffer_right , "proof right outside if else" );
241+ CHECK_ERROR (get_lemma_hash (proof , & right ));
192242 }
193243
194244 // Check left subtree
195245 const uint8_t * left ;
196246 if (start_index < (split_index + offset )) {
197247 uint32_t left_subtrie_size = split_index ;
198- if (left_subtrie_size == 1 ) {
199- left = proof -> hash ;
200-
201- buffer_left .ptr = left ;
202- buffer_left .len = CX_SHA256_SIZE ;
203- print_buffer (& buffer_left , "left inside if true" );
204- } else {
205- print_u32 ("left inside else:" , left_subtrie_size );
206- CHECK_ERROR (check_range_proof_inner (proof , start_index , left_subtrie_size , offset ));
207- left = proof -> hash ;
208- }
248+ CHECK_ERROR (get_subtree_hash (proof , start_index , left_subtrie_size , offset , & left ));
209249 } else {
210- left = proof -> lemmas_ctx .lemmas .data .buffer .ptr + CX_SHA256_SIZE * proof -> lemmas_ctx .last_index ;
211- if (proof -> lemmas_ctx .last_index < 0 ) {
212- return parser_value_out_of_range ;
213- }
214- proof -> lemmas_ctx .last_index -- ;
215-
216- buffer_left .ptr = left ;
217- buffer_left .len = CX_SHA256_SIZE ;
218- print_buffer (& buffer_left , "proof left outside if else" );
250+ CHECK_ERROR (get_lemma_hash (proof , & left ));
219251 }
220252
221- print_string ("MERGING LEFT AND RIGHT" );
222-
223- buffer_left .ptr = left ;
224- buffer_left .len = CX_SHA256_SIZE ;
225- print_buffer (& buffer_left , "left outside if else" );
226-
227- buffer_right .ptr = right ;
228- buffer_right .len = CX_SHA256_SIZE ;
229- print_buffer (& buffer_right , "right outside if else" );
230253 merge_branches (left , right , proof -> hash );
231254
232255 return parser_ok ;
@@ -253,10 +276,10 @@ static parser_error_t get_hash_single_proof(uint32_t index, proof_t *proof) {
253276 uint32_t num_left_siblings = compute_num_left_siblings (index );
254277
255278 // Get the number of right siblings needed
256- if (num_left_siblings > proof -> lemmas_ctx . lemmas .entries ) {
279+ if (num_left_siblings > proof -> lemmas .entries ) {
257280 return parser_value_out_of_range ;
258281 }
259- uint32_t num_right_siblings = proof -> lemmas_ctx . lemmas .entries - num_left_siblings ;
282+ uint32_t num_right_siblings = proof -> lemmas .entries - num_left_siblings ;
260283 print_u32 ("num_left_siblings:" , num_left_siblings );
261284 print_u32 ("num_right_siblings:" , num_right_siblings );
262285
@@ -277,17 +300,22 @@ static parser_error_t get_hash_single_proof(uint32_t index, proof_t *proof) {
277300 * @return parser_error_t Error code indicating the result of the operation.
278301 */
279302parser_error_t get_root_hash (const merkle_proof_t * metadata , uint8_t metadataDigest [CX_SHA256_SIZE ]) {
303+ CHECK_INPUT (metadata );
304+ CHECK_INPUT (metadataDigest );
305+
280306 proof_t proof = {0 };
281307 proof .leaves = metadata -> leaves ;
282- proof .lemmas_ctx = metadata -> lemmas_ctx ;
308+ proof .lemmas = metadata -> lemmas ;
283309 proof .indices = metadata -> indices ;
310+ proof .lemma_index = metadata -> lemmas .entries - 1 ;
311+ MEMSET (proof .hash , 0 , CX_SHA256_SIZE );
284312
285313 print_buffer (& proof .leaves .data .buffer , "leaves data" );
286314 print_u32 ("leaves.qty:" , proof .leaves .entries );
287315 print_buffer (& proof .indices .indices .buffer , "indices" );
288316 print_u32 ("indices.qty:" , proof .indices .entries );
289- print_buffer (& proof .lemmas_ctx . lemmas .data .buffer , "lemmas" );
290- print_u32 ("lemmas.qty:" , proof .lemmas_ctx . lemmas .entries );
317+ print_buffer (& proof .lemmas .data .buffer , "lemmas" );
318+ print_u32 ("lemmas.qty:" , proof .lemmas .entries );
291319
292320 uint32_t leaves_start = 0 ;
293321 CHECK_ERROR (read_u32 (& proof .indices .indices , & leaves_start ));
@@ -301,12 +329,17 @@ parser_error_t get_root_hash(const merkle_proof_t *metadata, uint8_t metadataDig
301329
302330parser_error_t verify_merkle_proofs (const merkle_proof_t * metadata ) {
303331 CHECK_INPUT (metadata );
332+ CHECK_INPUT (metadata -> root_hash .ptr );
333+
334+ if (metadata -> root_hash .len < CX_SHA256_SIZE ) {
335+ return parser_unexpected_buffer_end ;
336+ }
304337
305338 uint8_t root_hash [CX_SHA256_SIZE ] = {0 };
306339 CHECK_ERROR (get_root_hash (metadata , root_hash ));
307340
308341 // compare root_hash received with computed root_hash
309- if (memcmp (metadata -> root_hash .ptr , root_hash , 32 ) != 0 ) {
342+ if (memcmp (metadata -> root_hash .ptr , root_hash , CX_SHA256_SIZE ) != 0 ) {
310343 return parser_unexpected_root_hash ;
311344 }
312345
0 commit comments