Select one of the symbols to view example projects that use it.
 
Outline
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "hardware/sha256.h"
#include "pico/bootrom/lock.h"
#include "pico/sha256.h"
#include "pico/time.h"
#define SHA256_PADDING_DATA_BYTES
#define SHA256_BLOCK_SIZE_BYTES
pico_sha256_lock(pico_sha256_state_t *)
pico_sha256_unlock(pico_sha256_state_t *)
pico_sha256_try_start(pico_sha256_state_t *, enum sha256_endianness, bool)
pico_sha256_start_blocking_until(pico_sha256_state_t *, enum sha256_endianness, bool, absolute_time_t)
write_to_hardware(pico_sha256_state_t *, const uint8_t *, size_t)
update_internal(pico_sha256_state_t *, const uint8_t *, size_t)
add_zero_bytes(pico_sha256_state_t *, size_t)
pico_sha256_update(pico_sha256_state_t *, const uint8_t *, size_t)
pico_sha256_update_blocking(pico_sha256_state_t *, const uint8_t *, size_t)
write_padding(pico_sha256_state_t *)
pico_sha256_finish(pico_sha256_state_t *, sha256_result_t *)
Files
loading...
SourceVuRaspberry Pi Pico SDK and ExamplesPicoSDKsrc/rp2_common/pico_sha256/sha256.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * Copyright (c) 2024 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause *//* ... */ #include <stdio.h> #include <string.h> #include <inttypes.h> #include "hardware/sha256.h" #include "pico/bootrom/lock.h" #include "pico/sha256.h" #include "pico/time.h" 7 includes // We add one 0x80 byte, then 8 bytes for the size #define SHA256_PADDING_DATA_BYTES 9 #define SHA256_BLOCK_SIZE_BYTES 64 bool __weak pico_sha256_lock(pico_sha256_state_t *state) { if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256)) return false; state->locked = true; return true; }{ ... } void __weak pico_sha256_unlock(pico_sha256_state_t *state) { assert(state->locked); bootrom_release_lock(BOOTROM_LOCK_SHA_256); state->locked = false; }{ ... } int pico_sha256_try_start(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma) { memset(state, 0, sizeof(*state)); if (!pico_sha256_lock(state)) return PICO_ERROR_RESOURCE_IN_USE; state->endianness = endianness; if (use_dma) { state->channel = (int8_t)dma_claim_unused_channel(false); if (state->channel < 0) { pico_sha256_unlock(state); return PICO_ERROR_INSUFFICIENT_RESOURCES; }if (state->channel < 0) { ... } state->config = dma_channel_get_default_config(state->channel); channel_config_set_transfer_data_size(&state->config, DMA_SIZE_8); channel_config_set_read_increment(&state->config, true); channel_config_set_write_increment(&state->config, false); channel_config_set_dreq(&state->config, DREQ_SHA256); sha256_set_dma_size(1); }if (use_dma) { ... } else { state->channel = -1; }else { ... } sha256_err_not_ready_clear(); sha256_set_bswap(endianness == SHA256_BIG_ENDIAN); sha256_start(); state->total_data_size = 0; return PICO_OK; }{ ... } int pico_sha256_start_blocking_until(pico_sha256_state_t *state, enum sha256_endianness endianness, bool use_dma, absolute_time_t until) { int rc; do { rc = pico_sha256_try_start(state, endianness, use_dma); if (rc != PICO_ERROR_RESOURCE_IN_USE) break; if (time_reached(until)) { rc = PICO_ERROR_TIMEOUT; break; }if (time_reached(until)) { ... } ...} while (true); return rc; }{ ... } static void write_to_hardware(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) { if (state->channel >= 0) { dma_channel_wait_for_finish_blocking(state->channel); assert(!sha256_err_not_ready()); sha256_wait_ready_blocking(); dma_channel_configure( state->channel, &state->config, sha256_get_write_addr(), data, data_size_bytes, true ); }if (state->channel >= 0) { ... } else { if (!state->cache_used && !(((uintptr_t)data)&3u)) { GCC_Like_Pragma("GCC diagnostic ignored \"-Wcast-align\"") const uint32_t *data32 = (const uint32_t *)data; // aligned writes while (data_size_bytes >= 4) { // write a whole word sha256_wait_ready_blocking(); sha256_put_word(*data32++); data_size_bytes -= 4; }while (data_size_bytes >= 4) { ... } data = (const uint8_t *)data32; }if (!state->cache_used && !(((uintptr_t)data)&3u)) { ... } while (data_size_bytes--) { state->cache.bytes[state->cache_used++] = *data++; if (state->cache_used == 4) { state->cache_used = 0; sha256_wait_ready_blocking(); sha256_put_word(state->cache.word); }if (state->cache_used == 4) { ... } }while (data_size_bytes--) { ... } }else { ... } }{ ... } static void update_internal(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) { assert(state->locked); // must finish off the last 64 byte block first or else sha256_err_not_ready will be true size_t bytes_left = ((state->total_data_size + (SHA256_BLOCK_SIZE_BYTES - 1)) & ~(SHA256_BLOCK_SIZE_BYTES - 1)) - state->total_data_size; if (bytes_left > data_size_bytes) bytes_left = data_size_bytes; if (bytes_left > 0) { write_to_hardware(state, data, bytes_left); state->total_data_size += bytes_left; data_size_bytes -= bytes_left; data += bytes_left; }if (bytes_left > 0) { ... } // Write the rest of the data if (data_size_bytes > 0) { write_to_hardware(state, data, data_size_bytes); state->total_data_size += data_size_bytes; }if (data_size_bytes > 0) { ... } }{ ... } static void add_zero_bytes(pico_sha256_state_t *state, size_t data_size_bytes) { uint32_t zero = 0; // todo: can be done a bit more efficiently with dma? assert(data_size_bytes < INT32_MAX); while((int32_t)data_size_bytes > 0) { update_internal(state, (uint8_t *)&zero, MIN(4, data_size_bytes)); data_size_bytes -= 4; }while ((int32_t)data_size_bytes > 0) { ... } }{ ... } void pico_sha256_update(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) { update_internal(state, data, data_size_bytes); }{ ... } void pico_sha256_update_blocking(pico_sha256_state_t *state, const uint8_t *data, size_t data_size_bytes) { update_internal(state, data, data_size_bytes); if (state->channel >= 0) { dma_channel_wait_for_finish_blocking(state->channel); }if (state->channel >= 0) { ... } }{ ... } // write the SHA-256 padding to hardware static void write_padding(pico_sha256_state_t *state) { // Has to be a multiple of 64 bytes uint64_t size = (state->total_data_size + SHA256_PADDING_DATA_BYTES + (SHA256_BLOCK_SIZE_BYTES - 1)) & ~(SHA256_BLOCK_SIZE_BYTES - 1); const size_t user_data_size = state->total_data_size; const size_t padding_size_bytes = size - state->total_data_size; // append a single '1' bit const uint8_t one_bit = 0x80; update_internal(state, &one_bit, 1); // Zero unused padding add_zero_bytes(state, padding_size_bytes - SHA256_PADDING_DATA_BYTES); // Add size in bits, big endian size = __builtin_bswap64(user_data_size * 8); update_internal(state, (uint8_t*)&size, sizeof(uint64_t)); // last write }{ ... } void pico_sha256_finish(pico_sha256_state_t *state, sha256_result_t *out) { assert(state->locked); // pass NULL to abandon the current hash in case of an error if (out) { write_padding(state); if (state->channel >= 0) { dma_channel_wait_for_finish_blocking(state->channel); assert(!sha256_err_not_ready()); }if (state->channel >= 0) { ... } sha256_wait_valid_blocking(); sha256_get_result(out, state->endianness); }if (out) { ... } if (state->channel >= 0) { dma_channel_cleanup(state->channel); dma_channel_unclaim(state->channel); state->channel = -1; }if (state->channel >= 0) { ... } pico_sha256_unlock(state); }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.