1 // Copyright 2017 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "crypto_hash_sha256.h"
16 #include "mbedtls/sha256.h"
17 #include <string.h>
18 
19 #ifdef MBEDTLS_SHA256_ALT
20 /* Wrapper only works if the libsodium context structure can be mapped
21    directly to the mbedTLS context structure.
22 
23    See extended comments in crypto_hash_sha512_mbedtls.c
24 */
25 #error "This wrapper only support standard software mbedTLS SHA"
26 #endif
27 
28 /* Sanity check that all the context fields have identical sizes
29    (this should be more or less given from the SHA256 algorithm)
30 
31    Note that the meaning of the fields is *not* all the same. In libsodium, SHA256 'count' is a 64-bit *bit* count. In
32    mbedTLS, 'total' is a 2x32-bit *byte* count (count[0] == MSB).
33 
34    For this implementation, we don't convert so the libsodium state structure actually holds a binary copy of the
35    mbedTLS totals. This doesn't matter inside libsodium's documented API, but would matter if any callers try to use
36    the state's bit count.
37 */
38 _Static_assert(sizeof(((crypto_hash_sha256_state *)0)->state) == sizeof(((mbedtls_sha256_context *)0)->state), "state mismatch");
39 _Static_assert(sizeof(((crypto_hash_sha256_state *)0)->count) == sizeof(((mbedtls_sha256_context *)0)->total), "count mismatch");
40 _Static_assert(sizeof(((crypto_hash_sha256_state *)0)->buf) == sizeof(((mbedtls_sha256_context *)0)->buffer), "buf mismatch");
41 
42 /* Inline functions to convert between mbedTLS & libsodium
43    context structures
44 */
45 
sha256_mbedtls_to_libsodium(crypto_hash_sha256_state * ls_state,const mbedtls_sha256_context * mb_ctx)46 static void sha256_mbedtls_to_libsodium(crypto_hash_sha256_state *ls_state, const mbedtls_sha256_context *mb_ctx)
47 {
48     memcpy(&ls_state->count, mb_ctx->total, sizeof(ls_state->count));
49     memcpy(ls_state->state, mb_ctx->state, sizeof(ls_state->state));
50     memcpy(ls_state->buf, mb_ctx->buffer, sizeof(ls_state->buf));
51 }
52 
sha256_libsodium_to_mbedtls(mbedtls_sha256_context * mb_ctx,crypto_hash_sha256_state * ls_state)53 static void sha256_libsodium_to_mbedtls(mbedtls_sha256_context *mb_ctx, crypto_hash_sha256_state *ls_state)
54 {
55     memcpy(mb_ctx->total, &ls_state->count, sizeof(mb_ctx->total));
56     memcpy(mb_ctx->state, ls_state->state, sizeof(mb_ctx->state));
57     memcpy(mb_ctx->buffer, ls_state->buf, sizeof(mb_ctx->buffer));
58     mb_ctx->is224 = 0;
59 }
60 
61 int
crypto_hash_sha256_init(crypto_hash_sha256_state * state)62 crypto_hash_sha256_init(crypto_hash_sha256_state *state)
63 {
64     mbedtls_sha256_context ctx;
65     mbedtls_sha256_init(&ctx);
66     int ret = mbedtls_sha256_starts_ret(&ctx, 0);
67     if (ret != 0) {
68         return ret;
69     }
70     sha256_mbedtls_to_libsodium(state, &ctx);
71     return 0;
72 }
73 
74 int
crypto_hash_sha256_update(crypto_hash_sha256_state * state,const unsigned char * in,unsigned long long inlen)75 crypto_hash_sha256_update(crypto_hash_sha256_state *state,
76                           const unsigned char *in, unsigned long long inlen)
77 {
78     mbedtls_sha256_context ctx;
79     sha256_libsodium_to_mbedtls(&ctx, state);
80     int ret = mbedtls_sha256_update_ret(&ctx, in, inlen);
81     if (ret != 0) {
82         return ret;
83     }
84     sha256_mbedtls_to_libsodium(state, &ctx);
85     return 0;
86 }
87 
88 int
crypto_hash_sha256_final(crypto_hash_sha256_state * state,unsigned char * out)89 crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out)
90 {
91     mbedtls_sha256_context ctx;
92     sha256_libsodium_to_mbedtls(&ctx, state);
93     return mbedtls_sha256_finish_ret(&ctx, out);
94 }
95 
96 int
crypto_hash_sha256(unsigned char * out,const unsigned char * in,unsigned long long inlen)97 crypto_hash_sha256(unsigned char *out, const unsigned char *in,
98                    unsigned long long inlen)
99 {
100     return mbedtls_sha256_ret(in, inlen, out, 0);
101 }
102