Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ns_sha256.c Source File

ns_sha256.c

00001 /*
00002  * Copyright (c) 2006-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 /*
00018  *  FIPS-180-2 compliant SHA-256 implementation
00019  *
00020  *  This file is derived from sha256.h in mbed TLS 2.3.0.
00021  */
00022 /*
00023  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
00024  *
00025  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
00026  */
00027 
00028 #include "nsconfig.h"
00029 #include "ns_sha256.h"
00030 
00031 #ifndef NS_USE_EXTERNAL_MBED_TLS
00032 
00033 #include <string.h>
00034 
00035 /* Implementation that should never be optimized out by the compiler */
00036 static void ns_zeroize(void *v, size_t n)
00037 {
00038     volatile unsigned char *p = v;
00039     while (n--) {
00040         *p++ = 0;
00041     }
00042 }
00043 
00044 /*
00045  * 32-bit integer manipulation macros (big endian)
00046  */
00047 #ifndef GET_UINT32_BE
00048 #define GET_UINT32_BE(n,b,i)                            \
00049 (                                                       \
00050     (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
00051         | ( (uint32_t) (b)[(i) + 1] << 16 )             \
00052         | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
00053         | ( (uint32_t) (b)[(i) + 3]       )             \
00054 )
00055 #endif
00056 
00057 #ifndef PUT_UINT32_BE
00058 #define PUT_UINT32_BE(n,b,i)                            \
00059 do {                                                    \
00060     (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
00061     (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
00062     (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
00063     (b)[(i) + 3] = (unsigned char) ( (n)       );       \
00064 } while( 0 )
00065 #endif
00066 
00067 void ns_sha256_init(ns_sha256_context *ctx)
00068 {
00069     memset(ctx, 0, sizeof(ns_sha256_context));
00070 }
00071 
00072 void ns_sha256_free(ns_sha256_context *ctx)
00073 {
00074     ns_zeroize(ctx, sizeof(ns_sha256_context));
00075 }
00076 
00077 void ns_sha256_clone(ns_sha256_context *dst,
00078                      const ns_sha256_context *src)
00079 {
00080     *dst = *src;
00081 }
00082 
00083 /*
00084  * SHA-256 context setup
00085  */
00086 void ns_sha256_starts(ns_sha256_context *ctx)
00087 {
00088     ctx->total [0] = 0;
00089     ctx->total [1] = 0;
00090 
00091     /* SHA-256 */
00092     ctx->state [0] = 0x6A09E667;
00093     ctx->state [1] = 0xBB67AE85;
00094     ctx->state [2] = 0x3C6EF372;
00095     ctx->state [3] = 0xA54FF53A;
00096     ctx->state [4] = 0x510E527F;
00097     ctx->state [5] = 0x9B05688C;
00098     ctx->state [6] = 0x1F83D9AB;
00099     ctx->state [7] = 0x5BE0CD19;
00100 }
00101 
00102 static const uint32_t K[] = {
00103     0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
00104     0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
00105     0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
00106     0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
00107     0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
00108     0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
00109     0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
00110     0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
00111     0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
00112     0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
00113     0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
00114     0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
00115     0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
00116     0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
00117     0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
00118     0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
00119 };
00120 
00121 #define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
00122 #define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
00123 
00124 #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
00125 #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
00126 
00127 #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
00128 #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
00129 
00130 #define F0(x,y,z) ((x & y) | (z & (x | y)))
00131 #define F1(x,y,z) (z ^ (x & (y ^ z)))
00132 
00133 #define R(t)                                              \
00134 (                                                         \
00135     W[t & 15] += S1(W[(t -  2) & 15]) + W[(t - 7) & 15] + \
00136                  S0(W[(t - 15) & 15])                     \
00137 )
00138 
00139 #define P(a,b,c,d,e,f,g,h,x,K)                  \
00140 {                                               \
00141     temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
00142     temp2 = S2(a) + F0(a,b,c);                  \
00143     d += temp1; h = temp1 + temp2;              \
00144 }
00145 
00146 static void ns_sha256_process(ns_sha256_context *ctx, const unsigned char data[64])
00147 {
00148     uint32_t temp1, temp2, W[16];
00149     uint32_t A[8];
00150     unsigned int i;
00151 
00152     for (i = 0; i < 8; i++) {
00153         A[i] = ctx->state [i];
00154     }
00155 
00156     for (i = 0; i < 64; i++) {
00157         uint32_t Wi;
00158         if (i < 16) {
00159             Wi = GET_UINT32_BE(W[i], data, 4 * i);
00160         } else {
00161             Wi = R(i);
00162         }
00163 
00164         P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], Wi, K[i]);
00165 
00166         temp1 = A[7];
00167         A[7] = A[6];
00168         A[6] = A[5];
00169         A[5] = A[4];
00170         A[4] = A[3];
00171         A[3] = A[2];
00172         A[2] = A[1];
00173         A[1] = A[0];
00174         A[0] = temp1;
00175     }
00176 
00177     for (i = 0; i < 8; i++) {
00178         ctx->state [i] += A[i];
00179     }
00180 }
00181 
00182 /*
00183  * SHA-256 process buffer
00184  */
00185 void ns_sha256_update(ns_sha256_context *ctx, const void *inputv,
00186                       size_t ilen)
00187 {
00188     const unsigned char *input = inputv;
00189     size_t fill;
00190     uint32_t left;
00191 
00192     if (ilen == 0) {
00193         return;
00194     }
00195 
00196     left = ctx->total [0] & 0x3F;
00197     fill = 64 - left;
00198 
00199     ctx->total [0] += (uint32_t) ilen;
00200     ctx->total [0] &= 0xFFFFFFFF;
00201 
00202     if (ctx->total [0] < (uint32_t) ilen) {
00203         ctx->total [1]++;
00204     }
00205 
00206     if (left && ilen >= fill) {
00207         memcpy((void *)(ctx->buffer  + left), input, fill);
00208         ns_sha256_process(ctx, ctx->buffer );
00209         input += fill;
00210         ilen  -= fill;
00211         left = 0;
00212     }
00213 
00214     while (ilen >= 64) {
00215         ns_sha256_process(ctx, input);
00216         input += 64;
00217         ilen  -= 64;
00218     }
00219 
00220     if (ilen > 0) {
00221         memcpy((void *)(ctx->buffer  + left), input, ilen);
00222     }
00223 }
00224 
00225 /*
00226  * SHA-256 final digest
00227  */
00228 void ns_sha256_finish_nbits(ns_sha256_context *ctx, void *outputv, unsigned obits)
00229 {
00230     unsigned char *output = outputv;
00231     uint32_t last, padn;
00232     uint32_t high, low;
00233     unsigned char msglen[8];
00234     unsigned int i;
00235 
00236     high = (ctx->total [0] >> 29)
00237            | (ctx->total [1] <<  3);
00238     low  = (ctx->total [0] <<  3);
00239 
00240     PUT_UINT32_BE(high, msglen, 0);
00241     PUT_UINT32_BE(low,  msglen, 4);
00242 
00243     last = ctx->total [0] & 0x3F;
00244     padn = (last < 56) ? (56 - last) : (120 - last);
00245 
00246     /* Const compound literals need not designate distinct objects - this could
00247      * potentially save ROM over declaring the padding array.
00248      */
00249     ns_sha256_update(ctx, (const unsigned char[64]) {
00250         0x80
00251     }, padn);
00252     ns_sha256_update(ctx, msglen, 8);
00253 
00254     for (i = 0; i < 8 && obits > 0; i++, obits -= 32) {
00255         PUT_UINT32_BE(ctx->state [i], output, 4 * i);
00256     }
00257 }
00258 
00259 void ns_sha256_finish(ns_sha256_context *ctx, void *output)
00260 {
00261     ns_sha256_finish_nbits(ctx, output, 256);
00262 }
00263 
00264 /*
00265  * output = SHA-256( input buffer )
00266  */
00267 void ns_sha256_nbits(const void *input, size_t ilen,
00268                      void *output, unsigned obits)
00269 {
00270     ns_sha256_context ctx;
00271 
00272     ns_sha256_init(&ctx);
00273     ns_sha256_starts(&ctx);
00274     ns_sha256_update(&ctx, input, ilen);
00275     ns_sha256_finish_nbits(&ctx, output, obits);
00276     ns_sha256_free(&ctx);
00277 }
00278 
00279 void ns_sha256(const void *input, size_t ilen,
00280                void *output)
00281 {
00282     ns_sha256_nbits(input, ilen, output, 256);
00283 }
00284 #endif /* NS_USE_EXTERNAL_MBED_TLS */