struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / support / regression / tests / lonesha256.c
blobc7bec37bf1071fc3ce79db1290805e616fa32cd2
1 /*
2 sha256.c
3 sha256 hash function (once gave wrong result on gbz80)
5 Test uses the implementation from lonesha256.
6 */
8 #include <testfwk.h>
10 #define LONESHA256_STATIC
12 #if !(defined(__SDCC_mcs51) && (defined(__SDCC_MODEL_SMALL) || defined(__SDCC_MODEL_MEDIUM) || defined(__SDCC_STACK_AUTO))) && !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) && !( (defined (__SDCC_mos6502) || defined(__SDCC_mos65c02 )) && defined(__SDCC_STACK_AUTO) ) // Lack of memory
15 lonesha256.h - Portable, endian-proof, single-file, single-function sha256 implementation, originally based on LibTomCrypt
17 To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring
18 rights to this software to the public domain worldwide. This software is distributed without any warranty.
19 You should have received a copy of the CC0 Public Domain Dedication along with this software.
20 If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
24 lonesha256 supports the following three configurations:
25 #define LONESHA256_EXTERN
26 Default, should be used when using lonesha256 in multiple compilation units within the same project.
27 #define LONESHA256_IMPLEMENTATION
28 Must be defined in exactly one source file within a project for lonesha256 to be found by the linker.
29 #define LONESHA256_STATIC
30 Defines the lonesha256() function as static, useful if lonesha256 is only used in a single compilation unit.
31 lonesha256 function
32 (static|extern) int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len)
33 writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out"
34 returns 0 on success, may return non-zero in future versions to indicate error
37 /* header section */
38 #ifndef LONESHA256_H
39 #define LONESHA256_H
41 /* process configuration */
42 #ifdef LONESHA256_STATIC
43 #define LONESHA256_IMPLEMENTATION
44 #define LSHA256DEF static
45 #else /* LONESHA256_EXTERN */
46 #define LSHA256DEF extern
47 #endif
49 /* includes */
50 #include <stddef.h> /* size_t */
52 /* lonesha256 declaration */
53 LSHA256DEF int lonesha256(unsigned char[32], const unsigned char*, size_t);
55 #endif /* LONESHA256_H */
57 /* implementation section */
58 #ifdef LONESHA256_IMPLEMENTATION
59 #undef LONESHA256_IMPLEMENTATION
61 /* includes */
62 #include <stdint.h> /* uint32_t, uint64_t */
63 #include <string.h> /* memcpy */
65 /* macros */
66 #define S(x, n) (((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((n)&31))|((uint32_t)(x)<<(uint32_t)((32-((n)&31))&31)))&0xFFFFFFFFUL)
67 #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
68 #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
69 #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
70 #define RND(a,b,c,d,e,f,g,h,i) \
71 t0 = h + (S(e, 6) ^ S(e, 11) ^ S(e, 25)) + (g ^ (e & (f ^ g))) + K[i] + W[i]; \
72 t1 = (S(a, 2) ^ S(a, 13) ^ S(a, 22)) + (((a | b) & c) | (a & b)); \
73 d += t0; \
74 h = t0 + t1;
75 #define STORE32H(x, y) \
76 (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
77 (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255);
78 #define LOAD32H(x, y) \
79 x = ((uint32_t)((y)[0]&255)<<24)|((uint32_t)((y)[1]&255)<<16)|((uint32_t)((y)[2]&255)<<8)|((uint32_t)((y)[3]&255));
80 #define STORE64H(x, y) \
81 (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
82 (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
83 (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
84 (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255);
85 #define SHA256_COMPRESS(buff) \
86 for (i = 0; i < 8; i++) S[i] = sha256_state[i]; \
87 for (i = 0; i < 16; i++) LOAD32H(W[i], buff + (4*i)); \
88 for (i = 16; i < 64; i++) W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; \
89 for (i = 0; i < 64; i++) { \
90 RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); \
91 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; \
92 S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; \
93 } \
94 for (i = 0; i < 8; i++) sha256_state[i] = sha256_state[i] + S[i];
96 /* lonesha256 function */
97 LSHA256DEF int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len) {
98 /* writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out"
99 * returns 0 on success, may return non-zero in future versions to indicate error */
100 int i;
101 const uint32_t K[64] = {
102 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
103 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
104 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
105 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
106 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
107 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
108 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
109 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
110 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
111 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
112 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
113 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
114 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
115 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
116 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
117 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
119 uint64_t sha256_length = 0;
120 uint32_t sha256_state[8] = {
121 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
122 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
123 }, S[8], W[64], t0, t1, t;
124 unsigned char sha256_buf[64];
125 /* process input in 64 byte chunks */
126 while (len >= 64) {
127 SHA256_COMPRESS(in);
128 sha256_length += 64 * 8;
129 in += 64;
130 len -= 64;
132 /* copy remaining bytes into sha256_buf */
133 memcpy(sha256_buf, in, len);
134 /* finish up (len now number of bytes in sha256_buf) */
135 sha256_length += len * 8;
136 sha256_buf[len++] = 0x80;
137 /* pad then compress if length is above 56 bytes */
138 if (len > 56) {
139 while (len < 64) sha256_buf[len++] = 0;
140 SHA256_COMPRESS(sha256_buf);
141 len = 0;
143 /* pad up to 56 bytes */
144 while (len < 56) sha256_buf[len++] = 0;
145 /* store length and compress */
146 STORE64H(sha256_length, sha256_buf + 56);
147 SHA256_COMPRESS(sha256_buf);
148 /* copy output */
149 for (i = 0; i < 8; i++) {
150 STORE32H(sha256_state[i], out + 4*i);
152 /* return */
153 return 0;
156 #endif /* LONESHA256_IMPLEMENTATION */
158 /* structs */
159 struct pair {
160 unsigned char* in; /* input string */
161 unsigned char out[32]; /* expected output */
164 /* known input/output pairs */
165 const struct pair pairs[] = {
166 /* 0: empty string */
169 {0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14,
170 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
171 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C,
172 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55}
174 /* 1: foobar string */
176 "foobar",
177 {0xC3, 0xAB, 0x8F, 0xF1, 0x37, 0x20, 0xE8, 0xAD,
178 0x90, 0x47, 0xDD, 0x39, 0x46, 0x6B, 0x3C, 0x89,
179 0x74, 0xE5, 0x92, 0xC2, 0xFA, 0x38, 0x3D, 0x4A,
180 0x39, 0x60, 0x71, 0x4C, 0xAE, 0xF0, 0xC4, 0xF2}
182 /* 2: quick brown fox */
184 "The quick brown fox jumps over the lazy dog",
185 {0xD7, 0xA8, 0xFB, 0xB3, 0x07, 0xD7, 0x80, 0x94,
186 0x69, 0xCA, 0x9A, 0xBC, 0xB0, 0x08, 0x2E, 0x4F,
187 0x8D, 0x56, 0x51, 0xE4, 0x6D, 0x3C, 0xDB, 0x76,
188 0x2D, 0x02, 0xD0, 0xBF, 0x37, 0xC9, 0xE5, 0x92}
191 #endif
193 void
194 testSha (void)
196 #if !defined(__SDCC_ds390) // Fails for unknown reason
197 #if !(defined(__SDCC_mcs51) && (defined(__SDCC_MODEL_SMALL) || defined(__SDCC_MODEL_MEDIUM) || defined(__SDCC_STACK_AUTO))) && !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) && !( (defined (__SDCC_mos6502) || defined(__SDCC_mos65c02 )) && defined(__SDCC_STACK_AUTO) ) // Lack of memory
198 int i;
200 for (i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
201 unsigned char out[32];
202 ASSERT(!lonesha256(out, pairs[i].in, strlen(pairs[i].in)));
203 ASSERT(!memcmp(out, pairs[i].out, sizeof(out)));
205 #endif
206 #endif