1 /*
2  * SHA-256 implementation with hardware ESP support added.
3  *
4  * SPDX-FileCopyrightText: The Mbed TLS Contributors
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
9  */
10 /*
11  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
12  *
13  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
14  */
15 
16 #include <mbedtls/build_info.h>
17 
18 #if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT)
19 
20 #include "mbedtls/sha256.h"
21 
22 #include <string.h>
23 
24 #if defined(MBEDTLS_SELF_TEST)
25 #if defined(MBEDTLS_PLATFORM_C)
26 #include "mbedtls/platform.h"
27 #else
28 #include <stdio.h>
29 #define mbedtls_printf printf
30 #endif /* MBEDTLS_PLATFORM_C */
31 #endif /* MBEDTLS_SELF_TEST */
32 
33 #include "sha/sha_dma.h"
34 
35 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)36 static void mbedtls_zeroize( void *v, size_t n )
37 {
38     volatile unsigned char *p = v;
39     while ( n-- ) {
40         *p++ = 0;
41     }
42 }
43 
44 /*
45  * 32-bit integer manipulation macros (big endian)
46  */
47 #ifndef GET_UINT32_BE
48 #define GET_UINT32_BE(n,b,i)                            \
49 do {                                                    \
50     (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
51         | ( (uint32_t) (b)[(i) + 1] << 16 )             \
52         | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
53         | ( (uint32_t) (b)[(i) + 3]       );            \
54 } while( 0 )
55 #endif
56 
57 #ifndef PUT_UINT32_BE
58 #define PUT_UINT32_BE(n,b,i)                            \
59 do {                                                    \
60     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
61     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
62     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
63     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
64 } while( 0 )
65 #endif
66 
mbedtls_sha256_init(mbedtls_sha256_context * ctx)67 void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
68 {
69     memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
70 }
71 
mbedtls_sha256_free(mbedtls_sha256_context * ctx)72 void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
73 {
74     if ( ctx == NULL ) {
75         return;
76     }
77 
78     mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
79 }
80 
mbedtls_sha256_clone(mbedtls_sha256_context * dst,const mbedtls_sha256_context * src)81 void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
82                            const mbedtls_sha256_context *src )
83 {
84     *dst = *src;
85 }
86 
87 /*
88  * SHA-256 context setup
89  */
mbedtls_sha256_starts(mbedtls_sha256_context * ctx,int is224)90 int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
91 {
92     memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
93 
94     if ( is224 ) {
95         ctx->mode = SHA2_224;
96     } else {
97         ctx->mode = SHA2_256;
98     }
99 
100     return 0;
101 }
102 
esp_internal_sha_update_state(mbedtls_sha256_context * ctx)103 static void esp_internal_sha_update_state(mbedtls_sha256_context *ctx)
104 {
105     if (ctx->sha_state == ESP_SHA256_STATE_INIT) {
106         ctx->first_block = true;
107         ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS;
108     } else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) {
109         ctx->first_block = false;
110         esp_sha_write_digest_state(ctx->mode, ctx->state);
111     }
112 }
113 
mbedtls_internal_sha256_process(mbedtls_sha256_context * ctx,const unsigned char data[64])114 int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
115 {
116     int ret = -1;
117     esp_sha_acquire_hardware();
118     esp_internal_sha_update_state(ctx);
119 
120     ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block);
121     if (ret != 0) {
122         esp_sha_release_hardware();
123         return ret;
124     }
125 
126     esp_sha_read_digest_state(ctx->mode, ctx->state);
127     esp_sha_release_hardware();
128 
129     return ret;
130 }
131 
132 /*
133  * SHA-256 process buffer
134  */
mbedtls_sha256_update(mbedtls_sha256_context * ctx,const unsigned char * input,size_t ilen)135 int mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
136                                size_t ilen )
137 {
138     size_t fill;
139     uint32_t left, len, local_len = 0;
140 
141     if ( ilen == 0 ) {
142         return 0;
143     }
144 
145     left = ctx->total[0] & 0x3F;
146     fill = 64 - left;
147 
148     ctx->total[0] += (uint32_t) ilen;
149     ctx->total[0] &= 0xFFFFFFFF;
150 
151     if ( ctx->total[0] < (uint32_t) ilen ) {
152         ctx->total[1]++;
153     }
154 
155     /* Check if any data pending from previous call to this API */
156     if ( left && ilen >= fill ) {
157         memcpy( (void *) (ctx->buffer + left), input, fill );
158 
159         input += fill;
160         ilen  -= fill;
161         left = 0;
162         local_len = 64;
163     }
164 
165     len = (ilen / 64) * 64;
166 
167     if ( len || local_len) {
168         esp_sha_acquire_hardware();
169         esp_internal_sha_update_state(ctx);
170 
171         int ret = esp_sha_dma(ctx->mode, input, len,  ctx->buffer, local_len, ctx->first_block);
172 
173         if (ret != 0) {
174             esp_sha_release_hardware();
175             return ret;
176         }
177 
178         esp_sha_read_digest_state(ctx->mode, ctx->state);
179 
180         esp_sha_release_hardware();
181     }
182 
183     if ( ilen > 0 ) {
184         memcpy( (void *) (ctx->buffer + left), input + len, ilen - len );
185     }
186 
187     return 0;
188 }
189 
190 static const unsigned char sha256_padding[64] = {
191     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
194     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
195 };
196 
197 /*
198  * SHA-256 final digest
199  */
mbedtls_sha256_finish(mbedtls_sha256_context * ctx,unsigned char * output)200 int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char *output )
201 {
202     int ret = -1;
203     uint32_t last, padn;
204     uint32_t high, low;
205     unsigned char msglen[8];
206 
207     high = ( ctx->total[0] >> 29 )
208            | ( ctx->total[1] <<  3 );
209     low  = ( ctx->total[0] <<  3 );
210 
211     PUT_UINT32_BE( high, msglen, 0 );
212     PUT_UINT32_BE( low,  msglen, 4 );
213 
214     last = ctx->total[0] & 0x3F;
215     padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
216 
217     if ( ( ret = mbedtls_sha256_update( ctx, sha256_padding, padn ) ) != 0 ) {
218         return ret;
219     }
220 
221     if ( ( ret = mbedtls_sha256_update( ctx, msglen, 8 ) ) != 0 ) {
222         return ret;
223     }
224 
225     memcpy(output, ctx->state, 32);
226 
227     return ret;
228 }
229 
230 #endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */
231