1 /*
2  * Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_SHA256_H
8 #define _PICO_SHA256_H
9 
10 #include "pico/time.h"
11 #include "hardware/dma.h"
12 #include "hardware/sha256.h"
13 
14 /** \file pico/sha256.h
15  *  \defgroup pico_sha256 pico_sha256
16  *
17  * \brief SHA-256 Hardware Accelerated implementation
18  *
19  * RP2350 is equipped with a hardware accelerated implementation of the SHA-256 hash algorithm.
20  * This should be much quicker than performing a SHA-256 checksum in software.
21  *
22  * \code
23  * pico_sha256_state_t state;
24  * if (pico_sha256_try_start(&state, SHA256_BIG_ENDIAN, true) == PICO_OK) {
25  *     sha256_result_t result;
26  *     pico_sha256_update(&state, some_data, sizeof(some_data));
27  *     pico_sha256_update(&state, some_more_data, sizeof(some_more_data));
28  *     pico_sha256_finish(&state, &result);
29  *     for (int i = 0; i < SHA256_RESULT_BYTES; i++) {
30  *         printf("%02x", result.bytes[i]);
31  *     }
32  * }
33  * \endcode
34  *
35  * \subsection sha256_example Example
36  * \addtogroup pico_sha256
37  *
38  * \include hello_sha256.c
39  */
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /*! \brief SHA-256 state used by the API
46  *  \ingroup pico_sha256
47  */
48 typedef struct pico_sha256_state {
49     enum sha256_endianness endianness;
50     int8_t channel;
51     bool locked;
52     uint8_t cache_used;
53     union {
54         uint32_t word;
55         uint8_t bytes[4];
56     } cache;
57     dma_channel_config config;
58     size_t total_data_size;
59 } pico_sha256_state_t;
60 
61 /*! \brief Start a SHA-256 calculation returning immediately with an error if the SHA-256 hardware is not available
62  *  \ingroup pico_sha256
63  *
64  * Initialises the hardware and state ready to start a new SHA-256 calculation.
65  * Only one instance can be started at any time.
66  *
67  * @param state A pointer to a pico_sha256_state_t instance
68  * @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
69  * @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
70  * @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started, otherwise an error is returned
71  */
72 int pico_sha256_try_start(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma);
73 
74 /*! \brief Start a SHA-256 calculation waiting for a defined period for the SHA-256 hardware to be available
75  *  \ingroup pico_sha256
76  *
77  * Initialises the hardware and state ready to start a new SHA-256 calculation.
78  * Only one instance can be started at any time.
79  *
80  * @param state A pointer to a pico_sha256_state_t instance
81  * @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
82  * @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
83  * @param until How long to wait for the SHA hardware to be available
84  * @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started in time, otherwise an error is returned
85  */
86 int pico_sha256_start_blocking_until(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma, absolute_time_t until);
87 
88 /*! \brief Start a SHA-256 calculation, blocking forever waiting until the SHA-256 hardware is available
89  *  \ingroup pico_sha256
90  *
91  * Initialises the hardware and state ready to start a new SHA-256 calculation.
92  * Only one instance can be started at any time.
93  *
94  * @param state A pointer to a pico_sha256_state_t instance
95  * @param endianness SHA256_BIG_ENDIAN or SHA256_LITTLE_ENDIAN for data in and data out
96  * @param use_dma Set to true to use DMA internally to copy data to hardware. This is quicker at the expense of hardware DMA resources.
97  * @return Returns PICO_OK if the hardware was available for use and the sha256 calculation could be started, otherwise an error is returned
98  */
pico_sha256_start_blocking(pico_sha256_state_t * state,enum sha256_endianness endianness,bool use_dma)99 static inline int pico_sha256_start_blocking(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma) {
100     return pico_sha256_start_blocking_until(state, endianness, use_dma, at_the_end_of_time);
101 }
102 
103 /*! \brief Add byte data to be SHA-256 calculation
104  *  \ingroup pico_sha256
105  *
106  * Add byte data to be SHA-256 calculation
107  * You may call this as many times as required to add all the data needed.
108  * You must have called pico_sha256_try_start (or equivalent) already.
109  *
110  * @param state A pointer to a pico_sha256_state_t instance
111  * @param data Pointer to the data to be added to the calculation
112  * @param data_size_bytes Amount of data to add
113  *
114  * @note This function may return before the copy has completed in which case the data passed to the function must remain valid and
115  * unchanged until a further call to pico_sha256_update or pico_sha256_finish. If this is not done, corrupt data may be used for the
116  * SHA-256 calculation giving an unexpected result.
117  */
118 void pico_sha256_update(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes);
119 
120 /*! \brief Add byte data to be SHA-256 calculation
121  *  \ingroup pico_sha256
122  *
123  * Add byte data to be SHA-256 calculation
124  * You may call this as many times as required to add all the data needed.
125  * You must have called pico_sha256_try_start already.
126  *
127  * @param state A pointer to a pico_sha256_state_t instance
128  * @param data Pointer to the data to be added to the calculation
129  * @param data_size_bytes Amount of data to add
130  *
131  * @note This function will only return when the data passed in is no longer required, so it can be freed or changed on return.
132  */
133 void pico_sha256_update_blocking(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes);
134 
135 /*! \brief Finish the SHA-256 calculation and return the result
136  *  \ingroup pico_sha256
137  *
138  * Ends the SHA-256 calculation freeing the hardware for use by another caller.
139  * You must have called pico_sha256_try_start already.
140  *
141  * @param state A pointer to a pico_sha256_state_t instance
142  * @param out The SHA-256 checksum
143  */
144 void pico_sha256_finish(pico_sha256_state_t *state, sha256_result_t *out);
145 
146 #ifdef __cplusplus
147 }
148 #endif
149 
150 #endif