iodine 0.1.21 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.travis.yml +23 -2
  4. data/CHANGELOG.md +9 -2
  5. data/README.md +232 -179
  6. data/Rakefile +13 -1
  7. data/bin/config.ru +63 -0
  8. data/bin/console +6 -0
  9. data/bin/echo +42 -32
  10. data/bin/http-hello +62 -0
  11. data/bin/http-playground +124 -0
  12. data/bin/playground +62 -0
  13. data/bin/poc/Gemfile.lock +23 -0
  14. data/bin/poc/README.md +37 -0
  15. data/bin/poc/config.ru +66 -0
  16. data/bin/poc/gemfile +1 -0
  17. data/bin/poc/www/index.html +57 -0
  18. data/bin/raw-rbhttp +35 -0
  19. data/bin/raw_broadcast +66 -0
  20. data/bin/test_with_faye +40 -0
  21. data/bin/ws-broadcast +108 -0
  22. data/bin/ws-echo +108 -0
  23. data/exe/iodine +59 -0
  24. data/ext/iodine/base64.c +264 -0
  25. data/ext/iodine/base64.h +72 -0
  26. data/ext/iodine/bscrypt-common.h +109 -0
  27. data/ext/iodine/bscrypt.h +49 -0
  28. data/ext/iodine/extconf.rb +41 -0
  29. data/ext/iodine/hex.c +123 -0
  30. data/ext/iodine/hex.h +70 -0
  31. data/ext/iodine/http.c +200 -0
  32. data/ext/iodine/http.h +128 -0
  33. data/ext/iodine/http1.c +402 -0
  34. data/ext/iodine/http1.h +56 -0
  35. data/ext/iodine/http1_simple_parser.c +473 -0
  36. data/ext/iodine/http1_simple_parser.h +59 -0
  37. data/ext/iodine/http_request.h +128 -0
  38. data/ext/iodine/http_response.c +1606 -0
  39. data/ext/iodine/http_response.h +393 -0
  40. data/ext/iodine/http_response_http1.h +374 -0
  41. data/ext/iodine/iodine_core.c +641 -0
  42. data/ext/iodine/iodine_core.h +70 -0
  43. data/ext/iodine/iodine_http.c +615 -0
  44. data/ext/iodine/iodine_http.h +19 -0
  45. data/ext/iodine/iodine_websocket.c +430 -0
  46. data/ext/iodine/iodine_websocket.h +21 -0
  47. data/ext/iodine/libasync.c +552 -0
  48. data/ext/iodine/libasync.h +117 -0
  49. data/ext/iodine/libreact.c +347 -0
  50. data/ext/iodine/libreact.h +244 -0
  51. data/ext/iodine/libserver.c +912 -0
  52. data/ext/iodine/libserver.h +435 -0
  53. data/ext/iodine/libsock.c +950 -0
  54. data/ext/iodine/libsock.h +478 -0
  55. data/ext/iodine/misc.c +181 -0
  56. data/ext/iodine/misc.h +76 -0
  57. data/ext/iodine/random.c +193 -0
  58. data/ext/iodine/random.h +48 -0
  59. data/ext/iodine/rb-call.c +127 -0
  60. data/ext/iodine/rb-call.h +60 -0
  61. data/ext/iodine/rb-libasync.h +79 -0
  62. data/ext/iodine/rb-rack-io.c +389 -0
  63. data/ext/iodine/rb-rack-io.h +17 -0
  64. data/ext/iodine/rb-registry.c +213 -0
  65. data/ext/iodine/rb-registry.h +33 -0
  66. data/ext/iodine/sha1.c +359 -0
  67. data/ext/iodine/sha1.h +85 -0
  68. data/ext/iodine/sha2.c +825 -0
  69. data/ext/iodine/sha2.h +138 -0
  70. data/ext/iodine/siphash.c +136 -0
  71. data/ext/iodine/siphash.h +15 -0
  72. data/ext/iodine/spnlock.h +235 -0
  73. data/ext/iodine/websockets.c +696 -0
  74. data/ext/iodine/websockets.h +120 -0
  75. data/ext/iodine/xor-crypt.c +189 -0
  76. data/ext/iodine/xor-crypt.h +107 -0
  77. data/iodine.gemspec +25 -18
  78. data/lib/iodine.rb +57 -58
  79. data/lib/iodine/http.rb +0 -189
  80. data/lib/iodine/protocol.rb +36 -245
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/rack/handler/iodine.rb +145 -2
  83. metadata +115 -37
  84. data/bin/core_http_test +0 -51
  85. data/bin/em playground +0 -56
  86. data/bin/hello_world +0 -75
  87. data/bin/setup +0 -7
  88. data/lib/iodine/client.rb +0 -5
  89. data/lib/iodine/core.rb +0 -102
  90. data/lib/iodine/core_init.rb +0 -143
  91. data/lib/iodine/http/hpack.rb +0 -553
  92. data/lib/iodine/http/http1.rb +0 -251
  93. data/lib/iodine/http/http2.rb +0 -507
  94. data/lib/iodine/http/rack_support.rb +0 -108
  95. data/lib/iodine/http/request.rb +0 -462
  96. data/lib/iodine/http/response.rb +0 -474
  97. data/lib/iodine/http/session.rb +0 -143
  98. data/lib/iodine/http/websocket_client.rb +0 -335
  99. data/lib/iodine/http/websocket_handler.rb +0 -101
  100. data/lib/iodine/http/websockets.rb +0 -336
  101. data/lib/iodine/io.rb +0 -56
  102. data/lib/iodine/logging.rb +0 -46
  103. data/lib/iodine/settings.rb +0 -158
  104. data/lib/iodine/ssl_connector.rb +0 -48
  105. data/lib/iodine/timers.rb +0 -95
data/ext/iodine/sha1.h ADDED
@@ -0,0 +1,85 @@
1
+ /*
2
+ (un)copyright: Boaz segev, 2016
3
+ License: Public Domain except for any non-public-domain algorithms, which are
4
+ subject to their own licenses.
5
+
6
+ Feel free to copy, use and enjoy in accordance with to the license(s).
7
+ */
8
+ #ifndef bscrypt_SHA1_H
9
+ #define bscrypt_SHA1_H
10
+ #include "bscrypt-common.h"
11
+ /* *****************************************************************************
12
+ C++ extern
13
+ */
14
+ #if defined(__cplusplus)
15
+ extern "C" {
16
+ #endif
17
+
18
+ /* ***************************************************************************
19
+ SHA-1 hashing
20
+ */
21
+
22
+ /**
23
+ SHA-1 hashing container - you should ignore the contents of this struct.
24
+
25
+ The `sha1_s` type will contain all the sha1 data required to perform the
26
+ hashing, managing it's encoding. If it's stack allocated, no freeing will be
27
+ required.
28
+
29
+ Use, for example:
30
+
31
+ #include "mini-crypt.h"
32
+ sha1_s sha1;
33
+ bscrypt.sha1_init(&sha1);
34
+ bscrypt.sha1_write(&sha1,
35
+ "The quick brown fox jumps over the lazy dog", 43);
36
+ char *hashed_result = bscrypt.sha1_result(&sha1);
37
+ */
38
+ typedef struct {
39
+ uint64_t length;
40
+ uint8_t buffer[64];
41
+ union {
42
+ uint32_t i[5];
43
+ unsigned char str[21];
44
+ } digest;
45
+ } sha1_s;
46
+
47
+ /**
48
+ Initialize or reset the `sha1` object. This must be performed before hashing
49
+ data using sha1.
50
+ */
51
+ sha1_s bscrypt_sha1_init(void);
52
+ /**
53
+ Writes data to the sha1 buffer.
54
+ */
55
+ void bscrypt_sha1_write(sha1_s *s, const void *data, size_t len);
56
+ /**
57
+ Finalizes the SHA1 hash, returning the Hashed data.
58
+
59
+ `sha1_result` can be called for the same object multiple times, but the
60
+ finalization will only be performed the first time this function is called.
61
+ */
62
+ char *bscrypt_sha1_result(sha1_s *s);
63
+
64
+ /**
65
+ An SHA1 helper function that performs initialiation, writing and finalizing.
66
+ */
67
+ static inline __unused char *bscrypt_sha1(sha1_s *s, const void *data,
68
+ size_t len) {
69
+ *s = bscrypt_sha1_init();
70
+ bscrypt_sha1_write(s, data, len);
71
+ return bscrypt_sha1_result(s);
72
+ }
73
+
74
+ #if defined(DEBUG) && DEBUG == 1
75
+ void bscrypt_test_sha1(void);
76
+ #endif
77
+
78
+ /* *****************************************************************************
79
+ C++ extern finish
80
+ */
81
+ #if defined(__cplusplus)
82
+ }
83
+ #endif
84
+
85
+ #endif
data/ext/iodine/sha2.c ADDED
@@ -0,0 +1,825 @@
1
+ /*
2
+ (un)copyright: Boaz segev, 2016
3
+ License: Public Domain except for any non-public-domain algorithms, which are
4
+ subject to their own licenses.
5
+
6
+ Feel free to copy, use and enjoy in accordance with to the license(s).
7
+ */
8
+ #ifndef _GNU_SOURCE
9
+ #define _GNU_SOURCE
10
+ #endif
11
+ #include "sha2.h"
12
+ /*****************************************************************************
13
+ Useful Macros
14
+ */
15
+
16
+ /** 32Bit left rotation, inlined. */
17
+ #define left_rotate32(i, bits) \
18
+ (((uint32_t)(i) << (bits)) | ((uint32_t)(i) >> (32 - (bits))))
19
+ /** 32Bit right rotation, inlined. */
20
+ #define right_rotate32(i, bits) \
21
+ (((uint32_t)(i) >> (bits)) | ((uint32_t)(i) << (32 - (bits))))
22
+ /** 64Bit left rotation, inlined. */
23
+ #define left_rotate64(i, bits) \
24
+ (((uint64_t)(i) << (bits)) | ((uint64_t)(i) >> (64 - (bits))))
25
+ /** 64Bit right rotation, inlined. */
26
+ #define right_rotate64(i, bits) \
27
+ (((uint64_t)(i) >> (bits)) | ((uint64_t)(i) << (64 - (bits))))
28
+ /** unknown size element - left rotation, inlined. */
29
+ #define left_rotate(i, bits) (((i) << (bits)) | ((i) >> (sizeof((i)) - (bits))))
30
+ /** unknown size element - right rotation, inlined. */
31
+ #define right_rotate(i, bits) \
32
+ (((i) >> (bits)) | ((i) << (sizeof((i)) - (bits))))
33
+ /** inplace byte swap 16 bit integer */
34
+ #define bswap16(i) \
35
+ do { \
36
+ (i) = (((i)&0xFFU) << 8) | (((i)&0xFF00U) >> 8); \
37
+ } while (0);
38
+ /** inplace byte swap 32 bit integer */
39
+ #define bswap32(i) \
40
+ do { \
41
+ (i) = (((i)&0xFFUL) << 24) | (((i)&0xFF00UL) << 8) | \
42
+ (((i)&0xFF0000UL) >> 8) | (((i)&0xFF000000UL) >> 24); \
43
+ } while (0);
44
+ /** inplace byte swap 64 bit integer */
45
+ #define bswap64(i) \
46
+ do { \
47
+ (i) = (((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \
48
+ (((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \
49
+ (((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \
50
+ (((i)&0xFF000000000000ULL) >> 40) | \
51
+ (((i)&0xFF00000000000000ULL) >> 56); \
52
+ } while (0);
53
+ /** get the byte swap value of a 128 bit ...??? */
54
+ #define gbswap128(c) \
55
+ (((*((__uint128_t *)(c))) & 0xFFULL) << 120) | \
56
+ (((*((__uint128_t *)(c))) & 0xFF00ULL) << 104) | \
57
+ (((*((__uint128_t *)(c))) & 0xFF0000ULL) << 88) | \
58
+ (((*((__uint128_t *)(c))) & 0xFF000000ULL) << 72) | \
59
+ (((*((__uint128_t *)(c))) & 0xFF00000000ULL) << 56) | \
60
+ (((*((__uint128_t *)(c))) & 0xFF0000000000ULL) << 40) | \
61
+ (((*((__uint128_t *)(c))) & 0xFF000000000000ULL) << 24) | \
62
+ (((*((__uint128_t *)(c))) & 0xFF00000000000000ULL) << 8) | \
63
+ (((*((__uint128_t *)(c))) & 0xFF0000000000000000ULL) >> 8) | \
64
+ (((*((__uint128_t *)(c))) & 0xFF000000000000000000ULL) >> 24) | \
65
+ (((*((__uint128_t *)(c))) & 0xFF00000000000000000000ULL) >> 40) | \
66
+ (((*((__uint128_t *)(c))) & 0xFF0000000000000000000000ULL) >> 56) | \
67
+ (((*((__uint128_t *)(c))) & 0xFF000000000000000000000000ULL) >> 72) | \
68
+ (((*((__uint128_t *)(c))) & 0xFF00000000000000000000000000ULL) >> 88) | \
69
+ (((*((__uint128_t *)(c))) & 0xFF0000000000000000000000000000ULL) >> 104)
70
+
71
+ #ifdef HAVE_X86Intrin
72
+ #undef bswap64
73
+ #define bswap64(i) \
74
+ { __asm__("bswapq %0" : "+r"(i) :); }
75
+
76
+ // shadow sched_yield as _mm_pause for spinwait
77
+ #define sched_yield() _mm_pause()
78
+ #endif
79
+
80
+ /* ***************************************************************************
81
+ SHA-2 hashing
82
+ */
83
+
84
+ const uint8_t sha2_padding[128] = {0x80, 0};
85
+
86
+ /* SHA-224 and SHA-256 constants */
87
+ static uint32_t sha2_256_words[] = {
88
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
89
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
90
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
91
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
92
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
93
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
94
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
95
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
96
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
97
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
98
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
99
+
100
+ /* SHA-512 and friends constants */
101
+ static uint64_t sha2_512_words[] = {
102
+ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
103
+ 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
104
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
105
+ 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
106
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
107
+ 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
108
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
109
+ 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
110
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
111
+ 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
112
+ 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
113
+ 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
114
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
115
+ 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
116
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
117
+ 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
118
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
119
+ 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
120
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
121
+ 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
122
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
123
+ 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
124
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
125
+ 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
126
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
127
+ 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
128
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
129
+
130
+ /* Specific Macros for the SHA-2 processing */
131
+
132
+ #define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & z))
133
+ #define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
134
+
135
+ #define Eps0_32(x) \
136
+ (right_rotate32((x), 2) ^ right_rotate32((x), 13) ^ right_rotate32((x), 22))
137
+ #define Eps1_32(x) \
138
+ (right_rotate32((x), 6) ^ right_rotate32((x), 11) ^ right_rotate32((x), 25))
139
+ #define Omg0_32(x) \
140
+ (right_rotate32((x), 7) ^ right_rotate32((x), 18) ^ (((x) >> 3)))
141
+ #define Omg1_32(x) \
142
+ (right_rotate32((x), 17) ^ right_rotate32((x), 19) ^ (((x) >> 10)))
143
+
144
+ #define Eps0_64(x) \
145
+ (right_rotate64((x), 28) ^ right_rotate64((x), 34) ^ right_rotate64((x), 39))
146
+ #define Eps1_64(x) \
147
+ (right_rotate64((x), 14) ^ right_rotate64((x), 18) ^ right_rotate64((x), 41))
148
+ #define Omg0_64(x) \
149
+ (right_rotate64((x), 1) ^ right_rotate64((x), 8) ^ (((x) >> 7)))
150
+ #define Omg1_64(x) \
151
+ (right_rotate64((x), 19) ^ right_rotate64((x), 61) ^ (((x) >> 6)))
152
+
153
+ #ifdef __BIG_ENDIAN__
154
+ /** Converts a 4 byte string to a uint32_t word. careful with alignment! */
155
+ #define str2word32(c) (*((uint32_t *)(c)))
156
+ #define str2word64(c) (*((uint64_t *)(c)))
157
+ #else
158
+ /**
159
+ Converts a 4 byte string to a Big Endian uint32_t word. (ignores alignment!)
160
+ */
161
+ #define str2word32(c) \
162
+ (((*((uint32_t *)(c))) & 0xFFUL) << 24) | \
163
+ (((*((uint32_t *)(c))) & 0xFF00UL) << 8) | \
164
+ (((*((uint32_t *)(c))) & 0xFF0000UL) >> 8) | \
165
+ (((*((uint32_t *)(c))) & 0xFF000000UL) >> 24)
166
+ #define str2word64(c) \
167
+ (((*((uint64_t *)(c))) & 0xFFULL) << 56) | \
168
+ (((*((uint64_t *)(c))) & 0xFF00ULL) << 40) | \
169
+ (((*((uint64_t *)(c))) & 0xFF0000ULL) << 24) | \
170
+ (((*((uint64_t *)(c))) & 0xFF000000ULL) << 8) | \
171
+ (((*((uint64_t *)(c))) & 0xFF00000000ULL) >> 8) | \
172
+ (((*((uint64_t *)(c))) & 0xFF0000000000ULL) >> 24) | \
173
+ (((*((uint64_t *)(c))) & 0xFF000000000000ULL) >> 40) | \
174
+ (((*((uint64_t *)(c))) & 0xFF00000000000000ULL) >> 56);
175
+ #endif
176
+
177
+ /**
178
+ Process the buffer once full.
179
+ */
180
+ static inline void perform_all_rounds(sha2_s *s, const uint8_t *data) {
181
+ if (s->type & 1) { /* 512 derived type */
182
+ // process values for the 64bit words
183
+ uint64_t a = s->digest.i64[0];
184
+ uint64_t b = s->digest.i64[1];
185
+ uint64_t c = s->digest.i64[2];
186
+ uint64_t d = s->digest.i64[3];
187
+ uint64_t e = s->digest.i64[4];
188
+ uint64_t f = s->digest.i64[5];
189
+ uint64_t g = s->digest.i64[6];
190
+ uint64_t h = s->digest.i64[7];
191
+ uint64_t t1, t2, w[80];
192
+ w[0] = str2word64(data);
193
+ w[1] = str2word64(data + 8);
194
+ w[2] = str2word64(data + 16);
195
+ w[3] = str2word64(data + 24);
196
+ w[4] = str2word64(data + 32);
197
+ w[5] = str2word64(data + 40);
198
+ w[6] = str2word64(data + 48);
199
+ w[7] = str2word64(data + 56);
200
+ w[8] = str2word64(data + 64);
201
+ w[9] = str2word64(data + 72);
202
+ w[10] = str2word64(data + 80);
203
+ w[11] = str2word64(data + 88);
204
+ w[12] = str2word64(data + 96);
205
+ w[13] = str2word64(data + 104);
206
+ w[14] = str2word64(data + 112);
207
+ w[15] = str2word64(data + 120);
208
+
209
+ #define perform_single_round(i) \
210
+ t1 = h + Eps1_64(e) + Ch(e, f, g) + sha2_512_words[i] + w[i]; \
211
+ t2 = Eps0_64(a) + Maj(a, b, c); \
212
+ h = g; \
213
+ g = f; \
214
+ f = e; \
215
+ e = d + t1; \
216
+ d = c; \
217
+ c = b; \
218
+ b = a; \
219
+ a = t1 + t2;
220
+
221
+ #define perform_4rounds(i) \
222
+ perform_single_round(i); \
223
+ perform_single_round(i + 1); \
224
+ perform_single_round(i + 2); \
225
+ perform_single_round(i + 3);
226
+
227
+ perform_4rounds(0);
228
+ perform_4rounds(4);
229
+ perform_4rounds(8);
230
+ perform_4rounds(12);
231
+
232
+ #undef perform_single_round
233
+ #define perform_single_round(i) \
234
+ w[i] = Omg1_64(w[i - 2]) + w[i - 7] + Omg0_64(w[i - 15]) + w[i - 16]; \
235
+ t1 = h + Eps1_64(e) + Ch(e, f, g) + sha2_512_words[i] + w[i]; \
236
+ t2 = Eps0_64(a) + Maj(a, b, c); \
237
+ h = g; \
238
+ g = f; \
239
+ f = e; \
240
+ e = d + t1; \
241
+ d = c; \
242
+ c = b; \
243
+ b = a; \
244
+ a = t1 + t2;
245
+
246
+ perform_4rounds(16);
247
+ perform_4rounds(20);
248
+ perform_4rounds(24);
249
+ perform_4rounds(28);
250
+ perform_4rounds(32);
251
+ perform_4rounds(36);
252
+ perform_4rounds(40);
253
+ perform_4rounds(44);
254
+ perform_4rounds(48);
255
+ perform_4rounds(52);
256
+ perform_4rounds(56);
257
+ perform_4rounds(60);
258
+ perform_4rounds(64);
259
+ perform_4rounds(68);
260
+ perform_4rounds(72);
261
+ perform_4rounds(76);
262
+
263
+ s->digest.i64[0] += a;
264
+ s->digest.i64[1] += b;
265
+ s->digest.i64[2] += c;
266
+ s->digest.i64[3] += d;
267
+ s->digest.i64[4] += e;
268
+ s->digest.i64[5] += f;
269
+ s->digest.i64[6] += g;
270
+ s->digest.i64[7] += h;
271
+ return;
272
+ } else {
273
+ // process values for the 32bit words
274
+ uint32_t a = s->digest.i32[0];
275
+ uint32_t b = s->digest.i32[1];
276
+ uint32_t c = s->digest.i32[2];
277
+ uint32_t d = s->digest.i32[3];
278
+ uint32_t e = s->digest.i32[4];
279
+ uint32_t f = s->digest.i32[5];
280
+ uint32_t g = s->digest.i32[6];
281
+ uint32_t h = s->digest.i32[7];
282
+ uint32_t t1, t2, w[64];
283
+
284
+ w[0] = str2word32(data);
285
+ w[1] = str2word32(data + 4);
286
+ w[2] = str2word32(data + 8);
287
+ w[3] = str2word32(data + 12);
288
+ w[4] = str2word32(data + 16);
289
+ w[5] = str2word32(data + 20);
290
+ w[6] = str2word32(data + 24);
291
+ w[7] = str2word32(data + 28);
292
+ w[8] = str2word32(data + 32);
293
+ w[9] = str2word32(data + 36);
294
+ w[10] = str2word32(data + 40);
295
+ w[11] = str2word32(data + 44);
296
+ w[12] = str2word32(data + 48);
297
+ w[13] = str2word32(data + 52);
298
+ w[14] = str2word32(data + 56);
299
+ w[15] = str2word32(data + 60);
300
+
301
+ #undef perform_single_round
302
+ #define perform_single_round(i) \
303
+ t1 = h + Eps1_32(e) + Ch(e, f, g) + sha2_256_words[i] + w[i]; \
304
+ t2 = Eps0_32(a) + Maj(a, b, c); \
305
+ h = g; \
306
+ g = f; \
307
+ f = e; \
308
+ e = d + t1; \
309
+ d = c; \
310
+ c = b; \
311
+ b = a; \
312
+ a = t1 + t2;
313
+
314
+ perform_4rounds(0);
315
+ perform_4rounds(4);
316
+ perform_4rounds(8);
317
+ perform_4rounds(12);
318
+
319
+ #undef perform_single_round
320
+ #define perform_single_round(i) \
321
+ w[i] = Omg1_32(w[i - 2]) + w[i - 7] + Omg0_32(w[i - 15]) + w[i - 16]; \
322
+ t1 = h + Eps1_32(e) + Ch(e, f, g) + sha2_256_words[i] + w[i]; \
323
+ t2 = Eps0_32(a) + Maj(a, b, c); \
324
+ h = g; \
325
+ g = f; \
326
+ f = e; \
327
+ e = d + t1; \
328
+ d = c; \
329
+ c = b; \
330
+ b = a; \
331
+ a = t1 + t2;
332
+
333
+ perform_4rounds(16);
334
+ perform_4rounds(20);
335
+ perform_4rounds(24);
336
+ perform_4rounds(28);
337
+ perform_4rounds(32);
338
+ perform_4rounds(36);
339
+ perform_4rounds(40);
340
+ perform_4rounds(44);
341
+ perform_4rounds(48);
342
+ perform_4rounds(52);
343
+ perform_4rounds(56);
344
+ perform_4rounds(60);
345
+
346
+ s->digest.i32[0] += a;
347
+ s->digest.i32[1] += b;
348
+ s->digest.i32[2] += c;
349
+ s->digest.i32[3] += d;
350
+ s->digest.i32[4] += e;
351
+ s->digest.i32[5] += f;
352
+ s->digest.i32[6] += g;
353
+ s->digest.i32[7] += h;
354
+ }
355
+ }
356
+
357
+ /*****************************************************************************
358
+ API
359
+ */
360
+
361
+ /**
362
+ Initialize/reset the SHA-2 object.
363
+
364
+ SHA-2 is actually a family of functions with different variants. When
365
+ initializing the SHA-2 container, you must select the variant you intend to
366
+ apply. The following are valid options (see the sha2_variant enum):
367
+
368
+ - SHA_512 (== 0)
369
+ - SHA_384
370
+ - SHA_512_224
371
+ - SHA_512_256
372
+ - SHA_256
373
+ - SHA_224
374
+
375
+ */
376
+ sha2_s bscrypt_sha2_init(sha2_variant variant) {
377
+ if (variant == SHA_256) {
378
+ return (sha2_s){
379
+ .type = SHA_256,
380
+ .digest.i32[0] = 0x6a09e667,
381
+ .digest.i32[1] = 0xbb67ae85,
382
+ .digest.i32[2] = 0x3c6ef372,
383
+ .digest.i32[3] = 0xa54ff53a,
384
+ .digest.i32[4] = 0x510e527f,
385
+ .digest.i32[5] = 0x9b05688c,
386
+ .digest.i32[6] = 0x1f83d9ab,
387
+ .digest.i32[7] = 0x5be0cd19,
388
+ };
389
+ } else if (variant == SHA_384) {
390
+ return (sha2_s){
391
+ .type = SHA_384,
392
+ .digest.i64[0] = 0xcbbb9d5dc1059ed8,
393
+ .digest.i64[1] = 0x629a292a367cd507,
394
+ .digest.i64[2] = 0x9159015a3070dd17,
395
+ .digest.i64[3] = 0x152fecd8f70e5939,
396
+ .digest.i64[4] = 0x67332667ffc00b31,
397
+ .digest.i64[5] = 0x8eb44a8768581511,
398
+ .digest.i64[6] = 0xdb0c2e0d64f98fa7,
399
+ .digest.i64[7] = 0x47b5481dbefa4fa4,
400
+ };
401
+ } else if (variant == SHA_512) {
402
+ return (sha2_s){
403
+ .type = SHA_512,
404
+ .digest.i64[0] = 0x6a09e667f3bcc908,
405
+ .digest.i64[1] = 0xbb67ae8584caa73b,
406
+ .digest.i64[2] = 0x3c6ef372fe94f82b,
407
+ .digest.i64[3] = 0xa54ff53a5f1d36f1,
408
+ .digest.i64[4] = 0x510e527fade682d1,
409
+ .digest.i64[5] = 0x9b05688c2b3e6c1f,
410
+ .digest.i64[6] = 0x1f83d9abfb41bd6b,
411
+ .digest.i64[7] = 0x5be0cd19137e2179,
412
+ };
413
+ } else if (variant == SHA_224) {
414
+ return (sha2_s){
415
+ .type = SHA_224,
416
+ .digest.i32[0] = 0xc1059ed8,
417
+ .digest.i32[1] = 0x367cd507,
418
+ .digest.i32[2] = 0x3070dd17,
419
+ .digest.i32[3] = 0xf70e5939,
420
+ .digest.i32[4] = 0xffc00b31,
421
+ .digest.i32[5] = 0x68581511,
422
+ .digest.i32[6] = 0x64f98fa7,
423
+ .digest.i32[7] = 0xbefa4fa4,
424
+ };
425
+ } else if (variant == SHA_512_224) {
426
+ return (sha2_s){
427
+ .type = SHA_512_224,
428
+ .digest.i64[0] = 0x8c3d37c819544da2,
429
+ .digest.i64[1] = 0x73e1996689dcd4d6,
430
+ .digest.i64[2] = 0x1dfab7ae32ff9c82,
431
+ .digest.i64[3] = 0x679dd514582f9fcf,
432
+ .digest.i64[4] = 0x0f6d2b697bd44da8,
433
+ .digest.i64[5] = 0x77e36f7304c48942,
434
+ .digest.i64[6] = 0x3f9d85a86a1d36c8,
435
+ .digest.i64[7] = 0x1112e6ad91d692a1,
436
+ };
437
+ } else if (variant == SHA_512_256) {
438
+ return (sha2_s){
439
+ .type = SHA_512_256,
440
+ .digest.i64[0] = 0x22312194fc2bf72c,
441
+ .digest.i64[1] = 0x9f555fa3c84c64c2,
442
+ .digest.i64[2] = 0x2393b86b6f53b151,
443
+ .digest.i64[3] = 0x963877195940eabd,
444
+ .digest.i64[4] = 0x96283ee2a88effe3,
445
+ .digest.i64[5] = 0xbe5e1e2553863992,
446
+ .digest.i64[6] = 0x2b0199fc2c85b8aa,
447
+ .digest.i64[7] = 0x0eb72ddc81c52ca2,
448
+ };
449
+ }
450
+ fprintf(stderr, "bscrypt SHA2 ERROR - variant unknown\n");
451
+ exit(2);
452
+ }
453
+
454
+ /**
455
+ Writes data to the SHA-2 buffer.
456
+ */
457
+ void bscrypt_sha2_write(sha2_s *s, const void *data, size_t len) {
458
+ size_t in_buffer;
459
+ size_t partial;
460
+ if (s->type & 1) { /* 512 type derived */
461
+ #if defined(HAS_UINT128)
462
+ in_buffer = s->length.i & 127;
463
+ s->length.i += len;
464
+ #else
465
+ in_buffer = s->length.words[0] & 127;
466
+ if (s->length.words[0] + len < s->length.words[0]) {
467
+ /* we are at wraping around the 64bit limit */
468
+ s->length.words[1] = (s->length.words[1] << 1) | 1;
469
+ }
470
+ s->length.words[0] += len;
471
+ #endif
472
+ partial = 128 - in_buffer;
473
+
474
+ if (partial > len) {
475
+ memcpy(s->buffer + in_buffer, data, len);
476
+ return;
477
+ }
478
+ if (in_buffer) {
479
+ memcpy(s->buffer + in_buffer, data, partial);
480
+ len -= partial;
481
+ data += partial;
482
+ perform_all_rounds(s, s->buffer);
483
+ }
484
+ while (len >= 128) {
485
+ perform_all_rounds(s, data);
486
+ data += 128;
487
+ len -= 128;
488
+ }
489
+ if (len) {
490
+ memcpy(s->buffer + in_buffer, data, len);
491
+ }
492
+ return;
493
+ }
494
+ /* else... NOT 512 bits derived (64bit base) */
495
+
496
+ in_buffer = s->length.words[0] & 63;
497
+ partial = 64 - in_buffer;
498
+
499
+ s->length.words[0] += len;
500
+
501
+ if (partial > len) {
502
+ memcpy(s->buffer + in_buffer, data, len);
503
+ return;
504
+ }
505
+ if (in_buffer) {
506
+ memcpy(s->buffer + in_buffer, data, partial);
507
+ len -= partial;
508
+ data += partial;
509
+ perform_all_rounds(s, s->buffer);
510
+ }
511
+ while (len >= 64) {
512
+ perform_all_rounds(s, data);
513
+ data += 64;
514
+ len -= 64;
515
+ }
516
+ if (len) {
517
+ memcpy(s->buffer + in_buffer, data, len);
518
+ }
519
+ return;
520
+ }
521
+
522
+ /**
523
+ Finalizes the SHA-2 hash, returning the Hashed data.
524
+
525
+ `sha2_result` can be called for the same object multiple times, but the
526
+ finalization will only be performed the first time this function is called.
527
+ */
528
+ char *bscrypt_sha2_result(sha2_s *s) {
529
+ if (s->type & 1) {
530
+ /* 512 bits derived hashing */
531
+
532
+ #if defined(HAS_UINT128)
533
+ size_t in_buffer = s->length.i & 127;
534
+ #else
535
+ size_t in_buffer = s->length.words[0] & 127;
536
+ #endif
537
+
538
+ if (in_buffer > 111) {
539
+ memcpy(s->buffer + in_buffer, sha2_padding, 128 - in_buffer);
540
+ perform_all_rounds(s, s->buffer);
541
+ memcpy(s->buffer, sha2_padding + 1, 112);
542
+ } else if (in_buffer != 111) {
543
+ memcpy(s->buffer + in_buffer, sha2_padding, 112 - in_buffer);
544
+ } else {
545
+ s->buffer[111] = sha2_padding[0];
546
+ }
547
+ /* store the length in BITS - alignment should be promised by struct */
548
+ /* this must the number in BITS, encoded as a BIG ENDIAN 64 bit number */
549
+
550
+ #if defined(HAS_UINT128)
551
+ s->length.i = s->length.i << 3;
552
+ #else
553
+ s->length.words[1] = (s->length.words[1] << 3) | (s->length.words[0] >> 61);
554
+ s->length.words[0] = s->length.words[0] << 3;
555
+ #endif
556
+
557
+ #ifndef __BIG_ENDIAN__
558
+ bswap64(s->length.words[0]);
559
+ bswap64(s->length.words[1]);
560
+ {
561
+ uint_fast64_t tmp = s->length.words[0];
562
+ s->length.words[0] = s->length.words[1];
563
+ s->length.words[1] = tmp;
564
+ }
565
+ #endif
566
+
567
+ #if defined(HAS_UINT128)
568
+ __uint128_t *len = (__uint128_t *)(s->buffer + 112);
569
+ *len = s->length.i;
570
+ #else
571
+ uint64_t *len = (uint64_t *)(s->buffer + 112);
572
+ len[0] = s->length.words[0];
573
+ len[1] = s->length.words[1];
574
+ #endif
575
+ perform_all_rounds(s, s->buffer);
576
+
577
+ /* change back to little endian, if required */
578
+ #ifndef __BIG_ENDIAN__
579
+ bswap64(s->digest.i64[0]);
580
+ bswap64(s->digest.i64[1]);
581
+ bswap64(s->digest.i64[2]);
582
+ bswap64(s->digest.i64[3]);
583
+ bswap64(s->digest.i64[4]);
584
+ bswap64(s->digest.i64[5]);
585
+ bswap64(s->digest.i64[6]);
586
+ bswap64(s->digest.i64[7]);
587
+ #endif
588
+ // set NULL bytes for SHA_224
589
+ if (s->type == SHA_512_224)
590
+ s->digest.str[28] = 0;
591
+ // set NULL bytes for SHA_256
592
+ else if (s->type == SHA_512_256)
593
+ s->digest.str[32] = 0;
594
+ // set NULL bytes for SHA_384
595
+ else if (s->type == SHA_384)
596
+ s->digest.str[48] = 0;
597
+ s->digest.str[64] = 0; /* sometimes the optimizer messes the NUL sequence */
598
+ // fprintf(stderr, "result requested, in hex, is:");
599
+ // for (size_t i = 0; i < 20; i++)
600
+ // fprintf(stderr, "%02x", (unsigned int)(s->digest.str[i] & 0xFF));
601
+ // fprintf(stderr, "\r\n");
602
+ return (char *)s->digest.str;
603
+ }
604
+
605
+ size_t in_buffer = s->length.words[0] & 63;
606
+ if (in_buffer > 55) {
607
+ memcpy(s->buffer + in_buffer, sha2_padding, 64 - in_buffer);
608
+ perform_all_rounds(s, s->buffer);
609
+ memcpy(s->buffer, sha2_padding + 1, 56);
610
+ } else if (in_buffer != 55) {
611
+ memcpy(s->buffer + in_buffer, sha2_padding, 56 - in_buffer);
612
+ } else {
613
+ s->buffer[55] = sha2_padding[0];
614
+ }
615
+ /* store the length in BITS - alignment should be promised by struct */
616
+ /* this must the number in BITS, encoded as a BIG ENDIAN 64 bit number */
617
+ uint64_t *len = (uint64_t *)(s->buffer + 56);
618
+ *len = s->length.words[0] << 3;
619
+ #ifndef __BIG_ENDIAN__
620
+ bswap64(*len);
621
+ #endif
622
+ perform_all_rounds(s, s->buffer);
623
+
624
+ /* change back to little endian, if required */
625
+ #ifndef __BIG_ENDIAN__
626
+
627
+ bswap32(s->digest.i32[0]);
628
+ bswap32(s->digest.i32[1]);
629
+ bswap32(s->digest.i32[2]);
630
+ bswap32(s->digest.i32[3]);
631
+ bswap32(s->digest.i32[4]);
632
+ bswap32(s->digest.i32[5]);
633
+ bswap32(s->digest.i32[6]);
634
+ bswap32(s->digest.i32[7]);
635
+
636
+ #endif
637
+ // set NULL bytes for SHA_224
638
+ if (s->type == SHA_224)
639
+ s->digest.str[28] = 0;
640
+ // fprintf(stderr, "SHA-2 result requested, in hex, is:");
641
+ // for (size_t i = 0; i < (s->type_512 ? 64 : 32); i++)
642
+ // fprintf(stderr, "%02x", (unsigned int)(s->digest.str[i] & 0xFF));
643
+ // fprintf(stderr, "\r\n");
644
+ return (char *)s->digest.str;
645
+ }
646
+
647
+ /*******************************************************************************
648
+ SHA-2 testing
649
+ */
650
+ #if defined(DEBUG) && DEBUG == 1
651
+
652
+ // SHA_512 = 1, SHA_512_256 = 3, SHA_512_224 = 5, SHA_384 = 7, SHA_256 = 2,
653
+ // SHA_224 = 4,
654
+
655
+ static char *sha2_variant_names[] = {
656
+ "unknown", "SHA_512", "SHA_256", "SHA_512_256",
657
+ "SHA_224", "SHA_512_224", "none", "SHA_384",
658
+ };
659
+
660
+ // clang-format off
661
+ #if defined(TEST_OPENSSL) && defined(__has_include) && __has_include(<openssl/sha.h>)
662
+ # include <openssl/sha.h>
663
+ # define HAS_OPEN_SSL 1
664
+ #endif
665
+ // clang-format on
666
+
667
+ void bscrypt_test_sha2(void) {
668
+ sha2_s s;
669
+ char *expect = NULL;
670
+ char *got = NULL;
671
+ char *str = "";
672
+ fprintf(stderr, "===================================\n");
673
+ fprintf(stderr, "bscrypt SHA-2 struct size: %lu\n", sizeof(sha2_s));
674
+ fprintf(stderr, "+ bscrypt");
675
+ // start tests
676
+ s = bscrypt_sha2_init(SHA_224);
677
+ bscrypt_sha2_write(&s, str, 0);
678
+ expect = "\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9\x47\x61\x02\xbb\x28\x82\x34\xc4"
679
+ "\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a\xc5\xb3\xe4\x2f";
680
+ got = bscrypt_sha2_result(&s);
681
+ if (strcmp(expect, got))
682
+ goto error;
683
+
684
+ s = bscrypt_sha2_init(SHA_256);
685
+ bscrypt_sha2_write(&s, str, 0);
686
+ expect =
687
+ "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27"
688
+ "\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55";
689
+ got = bscrypt_sha2_result(&s);
690
+ if (strcmp(expect, got))
691
+ goto error;
692
+
693
+ s = bscrypt_sha2_init(SHA_384);
694
+ bscrypt_sha2_write(&s, str, 0);
695
+ expect = "\x38\xb0\x60\xa7\x51\xac\x96\x38\x4c\xd9\x32\x7e"
696
+ "\xb1\xb1\xe3\x6a\x21\xfd\xb7\x11\x14\xbe\x07\x43\x4c\x0c"
697
+ "\xc7\xbf\x63\xf6\xe1\xda\x27\x4e\xde\xbf\xe7\x6f\x65\xfb"
698
+ "\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b";
699
+ got = bscrypt_sha2_result(&s);
700
+ if (strcmp(expect, got))
701
+ goto error;
702
+
703
+ s = bscrypt_sha2_init(SHA_512);
704
+ bscrypt_sha2_write(&s, str, 0);
705
+ expect = "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d"
706
+ "\x80\x07\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21"
707
+ "\xd3\x6c\xe9\xce\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83"
708
+ "\x18\xd2\x87\x7e\xec\x2f\x63\xb9\x31\xbd\x47\x41\x7a\x81"
709
+ "\xa5\x38\x32\x7a\xf9\x27\xda\x3e";
710
+ got = bscrypt_sha2_result(&s);
711
+ if (strcmp(expect, got))
712
+ goto error;
713
+
714
+ s = bscrypt_sha2_init(SHA_512_224);
715
+ bscrypt_sha2_write(&s, str, 0);
716
+ expect = "\x6e\xd0\xdd\x02\x80\x6f\xa8\x9e\x25\xde\x06\x0c\x19\xd3"
717
+ "\xac\x86\xca\xbb\x87\xd6\xa0\xdd\xd0\x5c\x33\x3b\x84\xf4";
718
+ got = bscrypt_sha2_result(&s);
719
+ if (strcmp(expect, got))
720
+ goto error;
721
+
722
+ s = bscrypt_sha2_init(SHA_512_256);
723
+ bscrypt_sha2_write(&s, str, 0);
724
+ expect = "\xc6\x72\xb8\xd1\xef\x56\xed\x28\xab\x87\xc3\x62\x2c\x51\x14\x06"
725
+ "\x9b\xdd\x3a\xd7\xb8\xf9\x73\x74\x98\xd0\xc0\x1e\xce\xf0\x96\x7a";
726
+ got = bscrypt_sha2_result(&s);
727
+ if (strcmp(expect, got))
728
+ goto error;
729
+
730
+ s = bscrypt_sha2_init(SHA_512);
731
+ str = "god is a rotten tomato";
732
+ bscrypt_sha2_write(&s, str, strlen(str));
733
+ expect = "\x61\x97\x4d\x41\x9f\x77\x45\x21\x09\x4e\x95\xa3\xcb\x4d\xe4\x79"
734
+ "\x26\x32\x2f\x2b\xe2\x62\x64\x5a\xb4\x5d\x3f\x73\x69\xef\x46\x20"
735
+ "\xb2\xd3\xce\xda\xa9\xc2\x2c\xac\xe3\xf9\x02\xb2\x20\x5d\x2e\xfd"
736
+ "\x40\xca\xa0\xc1\x67\xe0\xdc\xdf\x60\x04\x3e\x4e\x76\x87\x82\x74";
737
+ got = bscrypt_sha2_result(&s);
738
+ if (strcmp(expect, got))
739
+ goto error;
740
+
741
+ // s = bscrypt_sha2_init(SHA_256);
742
+ // str = "The quick brown fox jumps over the lazy dog";
743
+ // bscrypt_sha2_write(&s, str, strlen(str));
744
+ // expect =
745
+ // "\xd7\xa8\xfb\xb3\x07\xd7\x80\x94\x69\xca\x9a\xbc\xb0\x08\x2e\x4f"
746
+ // "\x8d\x56\x51\xe4\x6d\x3c\xdb\x76\x2d\x02\xd0\xbf\x37\xc9\xe5\x92";
747
+ // got = bscrypt_sha2_result(&s);
748
+ // if (strcmp(expect, got))
749
+ // goto error;
750
+
751
+ s = bscrypt_sha2_init(SHA_224);
752
+ str = "The quick brown fox jumps over the lazy dog";
753
+ bscrypt_sha2_write(&s, str, strlen(str));
754
+ expect = "\x73\x0e\x10\x9b\xd7\xa8\xa3\x2b\x1c\xb9\xd9\xa0\x9a\xa2"
755
+ "\x32\x5d\x24\x30\x58\x7d\xdb\xc0\xc3\x8b\xad\x91\x15\x25";
756
+ got = bscrypt_sha2_result(&s);
757
+ if (strcmp(expect, got))
758
+ goto error;
759
+
760
+ fprintf(stderr, " SHA-2 passed.\n");
761
+
762
+ #ifdef HAS_OPEN_SSL
763
+ fprintf(stderr, "===================================\n");
764
+ fprintf(stderr, "bscrypt SHA-2 struct size: %lu\n", sizeof(sha2_s));
765
+ fprintf(stderr, "OpenSSL SHA-2/256 struct size: %lu\n", sizeof(SHA256_CTX));
766
+ fprintf(stderr, "OpenSSL SHA-2/512 struct size: %lu\n", sizeof(SHA512_CTX));
767
+ fprintf(stderr, "===================================\n");
768
+ SHA512_CTX s2;
769
+ SHA256_CTX s3;
770
+ unsigned char hash[SHA512_DIGEST_LENGTH + 1];
771
+ hash[SHA512_DIGEST_LENGTH] = 0;
772
+ clock_t start = clock();
773
+ for (size_t i = 0; i < 100000; i++) {
774
+ s = bscrypt_sha2_init(SHA_512);
775
+ bscrypt_sha2_write(&s, "The quick brown fox jumps over the lazy dog", 43);
776
+ bscrypt_sha2_result(&s);
777
+ }
778
+ fprintf(stderr, "bscrypt 100K SHA-2/512: %lf\n",
779
+ (double)(clock() - start) / CLOCKS_PER_SEC);
780
+
781
+ start = clock();
782
+ for (size_t i = 0; i < 100000; i++) {
783
+ SHA512_Init(&s2);
784
+ SHA512_Update(&s2, "The quick brown fox jumps over the lazy dog", 43);
785
+ SHA512_Final(hash, &s2);
786
+ }
787
+ fprintf(stderr, "OpenSSL 100K SHA-2/512: %lf\n",
788
+ (double)(clock() - start) / CLOCKS_PER_SEC);
789
+
790
+ start = clock();
791
+ for (size_t i = 0; i < 100000; i++) {
792
+ s = bscrypt_sha2_init(SHA_256);
793
+ bscrypt_sha2_write(&s, "The quick brown fox jumps over the lazy dog", 43);
794
+ bscrypt_sha2_result(&s);
795
+ }
796
+ fprintf(stderr, "bscrypt 100K SHA-2/256: %lf\n",
797
+ (double)(clock() - start) / CLOCKS_PER_SEC);
798
+
799
+ hash[SHA256_DIGEST_LENGTH] = 0;
800
+ start = clock();
801
+ for (size_t i = 0; i < 100000; i++) {
802
+ SHA256_Init(&s3);
803
+ SHA256_Update(&s3, "The quick brown fox jumps over the lazy dog", 43);
804
+ SHA256_Final(hash, &s3);
805
+ }
806
+ fprintf(stderr, "OpenSSL 100K SHA-2/256: %lf\n",
807
+ (double)(clock() - start) / CLOCKS_PER_SEC);
808
+
809
+ fprintf(stderr, "===================================\n");
810
+ #endif
811
+
812
+ return;
813
+ goto error;
814
+ error:
815
+ fprintf(stderr, ":\n--- bscrypt SHA-2 Test FAILED!\ntype: "
816
+ "%s (%d)\nstring %s\nexpected:\n",
817
+ sha2_variant_names[s.type], s.type, str);
818
+ while (*expect)
819
+ fprintf(stderr, "%02x", *(expect++) & 0xFF);
820
+ fprintf(stderr, "\ngot:\n");
821
+ while (*got)
822
+ fprintf(stderr, "%02x", *(got++) & 0xFF);
823
+ fprintf(stderr, "\n");
824
+ }
825
+ #endif