xcrypt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +106 -0
  3. data/ext/libxcrypt/AUTHORS +38 -0
  4. data/ext/libxcrypt/COPYING.LIB +502 -0
  5. data/ext/libxcrypt/ChangeLog +239 -0
  6. data/ext/libxcrypt/INSTALL +380 -0
  7. data/ext/libxcrypt/LICENSING +152 -0
  8. data/ext/libxcrypt/Makefile.am +704 -0
  9. data/ext/libxcrypt/Makefile.in +4110 -0
  10. data/ext/libxcrypt/NEWS +630 -0
  11. data/ext/libxcrypt/README +1 -0
  12. data/ext/libxcrypt/README.md +179 -0
  13. data/ext/libxcrypt/THANKS +13 -0
  14. data/ext/libxcrypt/TODO +1 -0
  15. data/ext/libxcrypt/TODO.md +100 -0
  16. data/ext/libxcrypt/aclocal.m4 +2617 -0
  17. data/ext/libxcrypt/autogen.sh +33 -0
  18. data/ext/libxcrypt/autom4te.cache/output.0 +19884 -0
  19. data/ext/libxcrypt/autom4te.cache/output.1 +19884 -0
  20. data/ext/libxcrypt/autom4te.cache/output.2 +19884 -0
  21. data/ext/libxcrypt/autom4te.cache/output.3 +19885 -0
  22. data/ext/libxcrypt/autom4te.cache/requests +714 -0
  23. data/ext/libxcrypt/autom4te.cache/traces.0 +4088 -0
  24. data/ext/libxcrypt/autom4te.cache/traces.1 +1060 -0
  25. data/ext/libxcrypt/autom4te.cache/traces.2 +4088 -0
  26. data/ext/libxcrypt/autom4te.cache/traces.3 +1060 -0
  27. data/ext/libxcrypt/build-aux/ci/ci-log-dependency-versions +79 -0
  28. data/ext/libxcrypt/build-aux/ci/ci-log-logfiles +22 -0
  29. data/ext/libxcrypt/build-aux/ci/clang-gcov-wrapper +2 -0
  30. data/ext/libxcrypt/build-aux/ci/configure-wrapper +10 -0
  31. data/ext/libxcrypt/build-aux/ci/summarize-coverage +24 -0
  32. data/ext/libxcrypt/build-aux/m4/ax_append_compile_flags.m4 +46 -0
  33. data/ext/libxcrypt/build-aux/m4/ax_append_flag.m4 +50 -0
  34. data/ext/libxcrypt/build-aux/m4/ax_check_compile_flag.m4 +53 -0
  35. data/ext/libxcrypt/build-aux/m4/ax_check_vscript.m4 +142 -0
  36. data/ext/libxcrypt/build-aux/m4/ax_gcc_func_attribute.m4 +246 -0
  37. data/ext/libxcrypt/build-aux/m4/ax_require_defined.m4 +37 -0
  38. data/ext/libxcrypt/build-aux/m4/ax_valgrind_check.m4 +239 -0
  39. data/ext/libxcrypt/build-aux/m4/libtool.m4 +8488 -0
  40. data/ext/libxcrypt/build-aux/m4/ltoptions.m4 +467 -0
  41. data/ext/libxcrypt/build-aux/m4/ltsugar.m4 +124 -0
  42. data/ext/libxcrypt/build-aux/m4/ltversion.m4 +24 -0
  43. data/ext/libxcrypt/build-aux/m4/lt~obsolete.m4 +99 -0
  44. data/ext/libxcrypt/build-aux/m4/pkg_compat.m4 +88 -0
  45. data/ext/libxcrypt/build-aux/m4/zw_alignment.m4 +90 -0
  46. data/ext/libxcrypt/build-aux/m4/zw_automodern.m4 +307 -0
  47. data/ext/libxcrypt/build-aux/m4/zw_detect_asan.m4 +24 -0
  48. data/ext/libxcrypt/build-aux/m4/zw_endianness.m4 +152 -0
  49. data/ext/libxcrypt/build-aux/m4/zw_ld_wrap.m4 +47 -0
  50. data/ext/libxcrypt/build-aux/m4/zw_prog_perl.m4 +40 -0
  51. data/ext/libxcrypt/build-aux/m4/zw_simple_warnings.m4 +150 -0
  52. data/ext/libxcrypt/build-aux/m4/zw_static_assert.m4 +68 -0
  53. data/ext/libxcrypt/build-aux/m4-autogen/compile +364 -0
  54. data/ext/libxcrypt/build-aux/m4-autogen/config.guess +1815 -0
  55. data/ext/libxcrypt/build-aux/m4-autogen/config.sub +2354 -0
  56. data/ext/libxcrypt/build-aux/m4-autogen/depcomp +792 -0
  57. data/ext/libxcrypt/build-aux/m4-autogen/install-sh +541 -0
  58. data/ext/libxcrypt/build-aux/m4-autogen/ltmain.sh +11524 -0
  59. data/ext/libxcrypt/build-aux/m4-autogen/missing +236 -0
  60. data/ext/libxcrypt/build-aux/m4-autogen/test-driver +160 -0
  61. data/ext/libxcrypt/build-aux/scripts/BuildCommon.pm +712 -0
  62. data/ext/libxcrypt/build-aux/scripts/check-perlcritic-config +76 -0
  63. data/ext/libxcrypt/build-aux/scripts/compute-symver-floor +116 -0
  64. data/ext/libxcrypt/build-aux/scripts/expand-selected-hashes +80 -0
  65. data/ext/libxcrypt/build-aux/scripts/gen-crypt-h +131 -0
  66. data/ext/libxcrypt/build-aux/scripts/gen-crypt-hashes-h +141 -0
  67. data/ext/libxcrypt/build-aux/scripts/gen-crypt-symbol-vers-h +150 -0
  68. data/ext/libxcrypt/build-aux/scripts/gen-libcrypt-map +67 -0
  69. data/ext/libxcrypt/build-aux/scripts/move-if-change +84 -0
  70. data/ext/libxcrypt/build-aux/scripts/skip-if-exec-format-error +78 -0
  71. data/ext/libxcrypt/codecov.yml +4 -0
  72. data/ext/libxcrypt/config.h.in +303 -0
  73. data/ext/libxcrypt/configure +19885 -0
  74. data/ext/libxcrypt/configure.ac +549 -0
  75. data/ext/libxcrypt/doc/crypt.3 +512 -0
  76. data/ext/libxcrypt/doc/crypt.5 +343 -0
  77. data/ext/libxcrypt/doc/crypt_checksalt.3 +106 -0
  78. data/ext/libxcrypt/doc/crypt_gensalt.3 +285 -0
  79. data/ext/libxcrypt/doc/crypt_gensalt_ra.3 +1 -0
  80. data/ext/libxcrypt/doc/crypt_gensalt_rn.3 +1 -0
  81. data/ext/libxcrypt/doc/crypt_preferred_method.3 +68 -0
  82. data/ext/libxcrypt/doc/crypt_r.3 +1 -0
  83. data/ext/libxcrypt/doc/crypt_ra.3 +1 -0
  84. data/ext/libxcrypt/doc/crypt_rn.3 +1 -0
  85. data/ext/libxcrypt/lib/alg-des-tables.c +3858 -0
  86. data/ext/libxcrypt/lib/alg-des.c +269 -0
  87. data/ext/libxcrypt/lib/alg-des.h +74 -0
  88. data/ext/libxcrypt/lib/alg-gost3411-2012-const.h +313 -0
  89. data/ext/libxcrypt/lib/alg-gost3411-2012-core.c +238 -0
  90. data/ext/libxcrypt/lib/alg-gost3411-2012-core.h +51 -0
  91. data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.c +78 -0
  92. data/ext/libxcrypt/lib/alg-gost3411-2012-hmac.h +46 -0
  93. data/ext/libxcrypt/lib/alg-gost3411-2012-precalc.h +1426 -0
  94. data/ext/libxcrypt/lib/alg-gost3411-2012-ref.h +67 -0
  95. data/ext/libxcrypt/lib/alg-hmac-sha1.c +140 -0
  96. data/ext/libxcrypt/lib/alg-hmac-sha1.h +35 -0
  97. data/ext/libxcrypt/lib/alg-md4.c +270 -0
  98. data/ext/libxcrypt/lib/alg-md4.h +43 -0
  99. data/ext/libxcrypt/lib/alg-md5.c +291 -0
  100. data/ext/libxcrypt/lib/alg-md5.h +43 -0
  101. data/ext/libxcrypt/lib/alg-sha1.c +288 -0
  102. data/ext/libxcrypt/lib/alg-sha1.h +34 -0
  103. data/ext/libxcrypt/lib/alg-sha256.c +630 -0
  104. data/ext/libxcrypt/lib/alg-sha256.h +123 -0
  105. data/ext/libxcrypt/lib/alg-sha512.c +311 -0
  106. data/ext/libxcrypt/lib/alg-sha512.h +81 -0
  107. data/ext/libxcrypt/lib/alg-sm3-hmac.c +113 -0
  108. data/ext/libxcrypt/lib/alg-sm3-hmac.h +42 -0
  109. data/ext/libxcrypt/lib/alg-sm3.c +449 -0
  110. data/ext/libxcrypt/lib/alg-sm3.h +63 -0
  111. data/ext/libxcrypt/lib/alg-yescrypt-common.c +713 -0
  112. data/ext/libxcrypt/lib/alg-yescrypt-opt.c +1568 -0
  113. data/ext/libxcrypt/lib/alg-yescrypt-platform.c +106 -0
  114. data/ext/libxcrypt/lib/alg-yescrypt.h +360 -0
  115. data/ext/libxcrypt/lib/byteorder.h +164 -0
  116. data/ext/libxcrypt/lib/crypt-bcrypt.c +1061 -0
  117. data/ext/libxcrypt/lib/crypt-des-obsolete.c +215 -0
  118. data/ext/libxcrypt/lib/crypt-des.c +491 -0
  119. data/ext/libxcrypt/lib/crypt-gensalt-static.c +40 -0
  120. data/ext/libxcrypt/lib/crypt-gost-yescrypt.c +182 -0
  121. data/ext/libxcrypt/lib/crypt-md5.c +232 -0
  122. data/ext/libxcrypt/lib/crypt-nthash.c +134 -0
  123. data/ext/libxcrypt/lib/crypt-obsolete.h +40 -0
  124. data/ext/libxcrypt/lib/crypt-pbkdf1-sha1.c +260 -0
  125. data/ext/libxcrypt/lib/crypt-port.h +514 -0
  126. data/ext/libxcrypt/lib/crypt-scrypt.c +247 -0
  127. data/ext/libxcrypt/lib/crypt-sha256.c +308 -0
  128. data/ext/libxcrypt/lib/crypt-sha512.c +323 -0
  129. data/ext/libxcrypt/lib/crypt-sm3-yescrypt.c +189 -0
  130. data/ext/libxcrypt/lib/crypt-sm3.c +308 -0
  131. data/ext/libxcrypt/lib/crypt-static.c +44 -0
  132. data/ext/libxcrypt/lib/crypt-sunmd5.c +314 -0
  133. data/ext/libxcrypt/lib/crypt-yescrypt.c +177 -0
  134. data/ext/libxcrypt/lib/crypt.c +421 -0
  135. data/ext/libxcrypt/lib/crypt.h.in +249 -0
  136. data/ext/libxcrypt/lib/gen-des-tables.c +363 -0
  137. data/ext/libxcrypt/lib/hashes.conf +59 -0
  138. data/ext/libxcrypt/lib/libcrypt.map.in +48 -0
  139. data/ext/libxcrypt/lib/libcrypt.minver +97 -0
  140. data/ext/libxcrypt/lib/libxcrypt.pc.in +15 -0
  141. data/ext/libxcrypt/lib/util-base64.c +26 -0
  142. data/ext/libxcrypt/lib/util-gensalt-sha.c +88 -0
  143. data/ext/libxcrypt/lib/util-get-random-bytes.c +154 -0
  144. data/ext/libxcrypt/lib/util-make-failure-token.c +48 -0
  145. data/ext/libxcrypt/lib/util-xbzero.c +43 -0
  146. data/ext/libxcrypt/lib/util-xstrcpy.c +42 -0
  147. data/ext/libxcrypt/lib/xcrypt.h.in +58 -0
  148. data/ext/libxcrypt/libxcrypt.spec.rpkg +481 -0
  149. data/ext/libxcrypt/rpkg.conf +2 -0
  150. data/ext/libxcrypt/rpkg.macros +86 -0
  151. data/ext/libxcrypt/test/TestCommon.pm +326 -0
  152. data/ext/libxcrypt/test/alg-des.c +80 -0
  153. data/ext/libxcrypt/test/alg-gost3411-2012-hmac.c +90 -0
  154. data/ext/libxcrypt/test/alg-gost3411-2012.c +191 -0
  155. data/ext/libxcrypt/test/alg-hmac-sha1.c +187 -0
  156. data/ext/libxcrypt/test/alg-md4.c +111 -0
  157. data/ext/libxcrypt/test/alg-md5.c +134 -0
  158. data/ext/libxcrypt/test/alg-pbkdf-hmac-sha256.c +269 -0
  159. data/ext/libxcrypt/test/alg-sha1.c +111 -0
  160. data/ext/libxcrypt/test/alg-sha256.c +141 -0
  161. data/ext/libxcrypt/test/alg-sha512.c +170 -0
  162. data/ext/libxcrypt/test/alg-sm3-hmac.c +149 -0
  163. data/ext/libxcrypt/test/alg-sm3.c +168 -0
  164. data/ext/libxcrypt/test/alg-yescrypt.c +466 -0
  165. data/ext/libxcrypt/test/badsalt.c +726 -0
  166. data/ext/libxcrypt/test/badsetting.c +350 -0
  167. data/ext/libxcrypt/test/byteorder.c +254 -0
  168. data/ext/libxcrypt/test/checksalt.c +265 -0
  169. data/ext/libxcrypt/test/compile-strong-alias.c +43 -0
  170. data/ext/libxcrypt/test/crypt-badargs.c +392 -0
  171. data/ext/libxcrypt/test/crypt-gost-yescrypt.c +149 -0
  172. data/ext/libxcrypt/test/crypt-nested-call.c +180 -0
  173. data/ext/libxcrypt/test/crypt-sm3-yescrypt.c +149 -0
  174. data/ext/libxcrypt/test/crypt-too-long-phrase.c +157 -0
  175. data/ext/libxcrypt/test/des-cases.h +196 -0
  176. data/ext/libxcrypt/test/des-obsolete.c +206 -0
  177. data/ext/libxcrypt/test/des-obsolete_r.c +207 -0
  178. data/ext/libxcrypt/test/explicit-bzero.c +334 -0
  179. data/ext/libxcrypt/test/gensalt-bcrypt_x.c +54 -0
  180. data/ext/libxcrypt/test/gensalt-extradata.c +246 -0
  181. data/ext/libxcrypt/test/gensalt-nested-call.c +126 -0
  182. data/ext/libxcrypt/test/gensalt-nthash.c +65 -0
  183. data/ext/libxcrypt/test/gensalt.c +599 -0
  184. data/ext/libxcrypt/test/getrandom-fallbacks.c +295 -0
  185. data/ext/libxcrypt/test/getrandom-interface.c +211 -0
  186. data/ext/libxcrypt/test/ka-table-gen.py +945 -0
  187. data/ext/libxcrypt/test/ka-table.inc +5849 -0
  188. data/ext/libxcrypt/test/ka-tester.c +240 -0
  189. data/ext/libxcrypt/test/preferred-method.c +133 -0
  190. data/ext/libxcrypt/test/short-outbuf.c +119 -0
  191. data/ext/libxcrypt/test/special-char-salt.c +1160 -0
  192. data/ext/libxcrypt/test/symbols-compat.pl +137 -0
  193. data/ext/libxcrypt/test/symbols-renames.pl +107 -0
  194. data/ext/libxcrypt/test/symbols-static.pl +87 -0
  195. data/ext/xcrypt/xcrypt.c +9 -0
  196. data/lib/xcrypt/ffi.rb +76 -0
  197. data/lib/xcrypt/version.rb +5 -0
  198. data/lib/xcrypt.rb +89 -0
  199. metadata +267 -0
@@ -0,0 +1,308 @@
1
+ /* One way encryption based on the SHA256-based Unix crypt implementation.
2
+ *
3
+ * Written by Ulrich Drepper <drepper at redhat.com> in 2007 [1].
4
+ * Modified by Zack Weinberg <zackw at panix.com> in 2017, 2018.
5
+ * Composed by Björn Esser <besser82 at fedoraproject.org> in 2018.
6
+ * Modified by Björn Esser <besser82 at fedoraproject.org> in 2020.
7
+ * Modified by Tianjia Zhang <tianjia.zhang at linux.alibaba.com> in 2024.
8
+ * To the extent possible under law, the named authors have waived all
9
+ * copyright and related or neighboring rights to this work.
10
+ *
11
+ * See https://creativecommons.org/publicdomain/zero/1.0/ for further
12
+ * details.
13
+ *
14
+ * This file is a modified except from [2], lines 648 up to 909.
15
+ *
16
+ * [1] https://www.akkadia.org/drepper/sha-crypt.html
17
+ * [2] https://www.akkadia.org/drepper/SHA-crypt.txt
18
+ */
19
+
20
+ #include "crypt-port.h"
21
+ #include "alg-sm3.h"
22
+
23
+ #include <errno.h>
24
+ #include <stdio.h>
25
+ #include <stdlib.h>
26
+
27
+ #if INCLUDE_sm3crypt
28
+
29
+ /* Define our magic string to mark salt for SM3 "encryption"
30
+ replacement. */
31
+ static const char sm3_salt_prefix[] = "$sm3$";
32
+
33
+ /* Prefix for optional rounds specification. */
34
+ static const char sm3_rounds_prefix[] = "rounds=";
35
+
36
+ /* Maximum salt string length. */
37
+ #define SALT_LEN_MAX 16
38
+ /* Default number of rounds if not explicitly specified. */
39
+ #define ROUNDS_DEFAULT 5000
40
+ /* Minimum number of rounds. */
41
+ #define ROUNDS_MIN 1000
42
+ /* Maximum number of rounds. */
43
+ #define ROUNDS_MAX 999999999
44
+
45
+ /* The maximum possible length of a SM3-hashed password string,
46
+ including the terminating NUL character. Prefix (including its NUL)
47
+ + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX)
48
+ + salt (up to SALT_LEN_MAX chars) + '$' + hash (43 chars). */
49
+
50
+ #define LENGTH_OF_NUMBER(n) (sizeof #n - 1)
51
+
52
+ #define SM3_HASH_LENGTH \
53
+ (sizeof (sm3_salt_prefix) + sizeof (sm3_rounds_prefix) + \
54
+ LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43)
55
+
56
+ static_assert (SM3_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
57
+ "CRYPT_OUTPUT_SIZE is too small for SM3");
58
+
59
+ /* A sm3_buffer holds all of the sensitive intermediate data. */
60
+ struct sm3_buffer
61
+ {
62
+ sm3_ctx ctx;
63
+ uint8_t result[32];
64
+ uint8_t p_bytes[32];
65
+ uint8_t s_bytes[32];
66
+ };
67
+
68
+ static_assert (sizeof (struct sm3_buffer) <= ALG_SPECIFIC_SIZE,
69
+ "ALG_SPECIFIC_SIZE is too small for SM3crypt");
70
+
71
+
72
+ /* Feed CTX with LEN bytes of a virtual byte sequence consisting of
73
+ BLOCK repeated over and over indefinitely. */
74
+ static void
75
+ sm3_update_recycled (sm3_ctx *ctx,
76
+ unsigned char block[32], size_t len)
77
+ {
78
+ size_t cnt;
79
+ for (cnt = len; cnt >= 32; cnt -= 32)
80
+ sm3_update (ctx, block, 32);
81
+ sm3_update (ctx, block, cnt);
82
+ }
83
+
84
+ void
85
+ crypt_sm3crypt_rn (const char *phrase, size_t phr_size,
86
+ const char *setting, size_t ARG_UNUSED (set_size),
87
+ uint8_t *output, size_t out_size,
88
+ void *scratch, size_t scr_size)
89
+ {
90
+ /* This shouldn't ever happen, but... */
91
+ if (out_size < SM3_HASH_LENGTH
92
+ || scr_size < sizeof (struct sm3_buffer))
93
+ {
94
+ errno = ERANGE;
95
+ return;
96
+ }
97
+
98
+ struct sm3_buffer *buf = scratch;
99
+ sm3_ctx *ctx = &buf->ctx;
100
+ uint8_t *result = buf->result;
101
+ uint8_t *p_bytes = buf->p_bytes;
102
+ uint8_t *s_bytes = buf->s_bytes;
103
+ char *cp = (char *)output;
104
+ const char *salt = setting;
105
+
106
+ size_t salt_size;
107
+ size_t cnt;
108
+ /* Default number of rounds. */
109
+ size_t rounds = ROUNDS_DEFAULT;
110
+ bool rounds_custom = false;
111
+
112
+ /* Find beginning of salt string. The prefix should normally always
113
+ be present. Just in case it is not. */
114
+ if (strncmp (sm3_salt_prefix, salt, sizeof (sm3_salt_prefix) - 1) == 0)
115
+ /* Skip salt prefix. */
116
+ salt += sizeof (sm3_salt_prefix) - 1;
117
+
118
+ if (strncmp (salt, sm3_rounds_prefix, sizeof (sm3_rounds_prefix) - 1)
119
+ == 0)
120
+ {
121
+ const char *num = salt + sizeof (sm3_rounds_prefix) - 1;
122
+ /* Do not allow an explicit setting of zero rounds, nor of the
123
+ default number of rounds, nor leading zeroes on the rounds. */
124
+ if (!(*num >= '1' && *num <= '9'))
125
+ {
126
+ errno = EINVAL;
127
+ return;
128
+ }
129
+
130
+ errno = 0;
131
+ char *endp;
132
+ rounds = strtoul (num, &endp, 10);
133
+ if (endp == num || *endp != '$'
134
+ || rounds < ROUNDS_MIN
135
+ || rounds > ROUNDS_MAX
136
+ || errno)
137
+ {
138
+ errno = EINVAL;
139
+ return;
140
+ }
141
+ salt = endp + 1;
142
+ rounds_custom = true;
143
+ }
144
+
145
+ /* The salt ends at the next '$' or the end of the string.
146
+ Ensure ':' does not appear in the salt (it is used as a separator in /etc/passwd).
147
+ Also check for '\n', as in /etc/passwd the whole parameters of the user data must
148
+ be on a single line. */
149
+ salt_size = strcspn (salt, "$:\n");
150
+ if (!(salt[salt_size] == '$' || !salt[salt_size]))
151
+ {
152
+ errno = EINVAL;
153
+ return;
154
+ }
155
+
156
+ /* Ensure we do not use more salt than SALT_LEN_MAX. */
157
+ if (salt_size > SALT_LEN_MAX)
158
+ salt_size = SALT_LEN_MAX;
159
+
160
+ /* Compute alternate SM3 sum with input PHRASE, SALT, and PHRASE. The
161
+ final result will be added to the first context. */
162
+ sm3_init (ctx);
163
+
164
+ /* Add phrase. */
165
+ sm3_update (ctx, phrase, phr_size);
166
+
167
+ /* Add salt. */
168
+ sm3_update (ctx, salt, salt_size);
169
+
170
+ /* Add phrase again. */
171
+ sm3_update (ctx, phrase, phr_size);
172
+
173
+ /* Now get result of this (32 bytes). */
174
+ sm3_final (result, ctx);
175
+
176
+ /* Prepare for the real work. */
177
+ sm3_init (ctx);
178
+
179
+ /* Add the phrase string. */
180
+ sm3_update (ctx, phrase, phr_size);
181
+
182
+ /* The last part is the salt string. This must be at most 8
183
+ characters and it ends at the first `$' character (for
184
+ compatibility with existing implementations). */
185
+ sm3_update (ctx, salt, salt_size);
186
+
187
+ /* Add for any character in the phrase one byte of the alternate sum. */
188
+ for (cnt = phr_size; cnt > 32; cnt -= 32)
189
+ sm3_update (ctx, result, 32);
190
+ sm3_update (ctx, result, cnt);
191
+
192
+ /* Take the binary representation of the length of the phrase and for every
193
+ 1 add the alternate sum, for every 0 the phrase. */
194
+ for (cnt = phr_size; cnt > 0; cnt >>= 1)
195
+ if ((cnt & 1) != 0)
196
+ sm3_update (ctx, result, 32);
197
+ else
198
+ sm3_update (ctx, phrase, phr_size);
199
+
200
+ /* Create intermediate result. */
201
+ sm3_final (result, ctx);
202
+
203
+ /* Start computation of P byte sequence. */
204
+ sm3_init (ctx);
205
+
206
+ /* For every character in the password add the entire password. */
207
+ for (cnt = 0; cnt < phr_size; ++cnt)
208
+ sm3_update (ctx, phrase, phr_size);
209
+
210
+ /* Finish the digest. */
211
+ sm3_final (p_bytes, ctx);
212
+
213
+ /* Start computation of S byte sequence. */
214
+ sm3_init (ctx);
215
+
216
+ /* For every character in the password add the entire password. */
217
+ for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
218
+ sm3_update (ctx, salt, salt_size);
219
+
220
+ /* Finish the digest. */
221
+ sm3_final (s_bytes, ctx);
222
+
223
+ /* Repeatedly run the collected hash value through SM3 to burn
224
+ CPU cycles. */
225
+ for (cnt = 0; cnt < rounds; ++cnt)
226
+ {
227
+ /* New context. */
228
+ sm3_init (ctx);
229
+
230
+ /* Add phrase or last result. */
231
+ if ((cnt & 1) != 0)
232
+ sm3_update_recycled (ctx, p_bytes, phr_size);
233
+ else
234
+ sm3_update (ctx, result, 32);
235
+
236
+ /* Add salt for numbers not divisible by 3. */
237
+ if (cnt % 3 != 0)
238
+ sm3_update_recycled (ctx, s_bytes, salt_size);
239
+
240
+ /* Add phrase for numbers not divisible by 7. */
241
+ if (cnt % 7 != 0)
242
+ sm3_update_recycled (ctx, p_bytes, phr_size);
243
+
244
+ /* Add phrase or last result. */
245
+ if ((cnt & 1) != 0)
246
+ sm3_update (ctx, result, 32);
247
+ else
248
+ sm3_update_recycled (ctx, p_bytes, phr_size);
249
+
250
+ /* Create intermediate result. */
251
+ sm3_final (result, ctx);
252
+ }
253
+
254
+ /* Now we can construct the result string. It consists of four
255
+ parts, one of which is optional. We already know that there
256
+ is sufficient space at CP for the longest possible result string. */
257
+ memcpy (cp, sm3_salt_prefix, sizeof (sm3_salt_prefix) - 1);
258
+ cp += sizeof (sm3_salt_prefix) - 1;
259
+
260
+ if (rounds_custom)
261
+ {
262
+ int n = snprintf (cp, SM3_HASH_LENGTH - (sizeof (sm3_salt_prefix) - 1),
263
+ "%s%zu$", sm3_rounds_prefix, rounds);
264
+ cp += n;
265
+ }
266
+
267
+ memcpy (cp, salt, salt_size);
268
+ cp += salt_size;
269
+ *cp++ = '$';
270
+
271
+ #define b64_from_24bit(B2, B1, B0, N) \
272
+ do { \
273
+ unsigned int w = ((((unsigned int)(B2)) << 16) | \
274
+ (((unsigned int)(B1)) << 8) | \
275
+ ((unsigned int)(B0))); \
276
+ int n = (N); \
277
+ while (n-- > 0) \
278
+ { \
279
+ *cp++ = b64t[w & 0x3f]; \
280
+ w >>= 6; \
281
+ } \
282
+ } while (0)
283
+
284
+ b64_from_24bit (result[0], result[10], result[20], 4);
285
+ b64_from_24bit (result[21], result[1], result[11], 4);
286
+ b64_from_24bit (result[12], result[22], result[2], 4);
287
+ b64_from_24bit (result[3], result[13], result[23], 4);
288
+ b64_from_24bit (result[24], result[4], result[14], 4);
289
+ b64_from_24bit (result[15], result[25], result[5], 4);
290
+ b64_from_24bit (result[6], result[16], result[26], 4);
291
+ b64_from_24bit (result[27], result[7], result[17], 4);
292
+ b64_from_24bit (result[18], result[28], result[8], 4);
293
+ b64_from_24bit (result[9], result[19], result[29], 4);
294
+ b64_from_24bit (0, result[31], result[30], 3);
295
+
296
+ *cp = '\0';
297
+ }
298
+
299
+ void
300
+ gensalt_sm3crypt_rn (unsigned long count,
301
+ const uint8_t *rbytes, size_t nrbytes,
302
+ uint8_t *output, size_t output_size)
303
+ {
304
+ gensalt_sha_rn ("sm3", SALT_LEN_MAX, ROUNDS_DEFAULT, ROUNDS_MIN, ROUNDS_MAX,
305
+ count, rbytes, nrbytes, output, output_size);
306
+ }
307
+
308
+ #endif
@@ -0,0 +1,44 @@
1
+ /* Copyright (C) 2007-2017 Thorsten Kukuk
2
+ Copyright (C) 2019 Björn Esser
3
+
4
+ This library is free software; you can redistribute it and/or
5
+ modify it under the terms of the GNU Lesser General Public License
6
+ as published by the Free Software Foundation; either version 2.1 of
7
+ the License, or (at your option) any later version.
8
+
9
+ This library is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Lesser General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Lesser General Public
15
+ License along with this library; if not, see
16
+ <https://www.gnu.org/licenses/>. */
17
+
18
+ #include "crypt-port.h"
19
+
20
+ /* The functions that use global state objects are isolated in their
21
+ own files so that a statically-linked program that doesn't use them
22
+ will not have the state objects in its data segment. */
23
+
24
+ #if INCLUDE_crypt
25
+ char *
26
+ crypt (const char *key, const char *setting)
27
+ {
28
+ static struct crypt_data nr_crypt_ctx;
29
+ return crypt_r (key, setting, &nr_crypt_ctx);
30
+ }
31
+ SYMVER_crypt;
32
+ #endif
33
+
34
+ /* For code compatibility with old glibc. */
35
+ #if INCLUDE_fcrypt
36
+ strong_alias (crypt, fcrypt);
37
+ SYMVER_fcrypt;
38
+ #endif
39
+
40
+ /* For code compatibility with older versions (v3.1.1 and earlier). */
41
+ #if INCLUDE_crypt && INCLUDE_xcrypt
42
+ strong_alias (crypt, xcrypt);
43
+ SYMVER_xcrypt;
44
+ #endif
@@ -0,0 +1,314 @@
1
+ /* Copyright (c) 2018 Zack Weinberg.
2
+ * All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ *
13
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
+ * SUCH DAMAGE.
24
+ *
25
+ * This is a clean-room reimplementation of the Sun-MD5 password hash,
26
+ * based on the prose description of the algorithm in the Passlib v1.7.1
27
+ * documentation:
28
+ * https://passlib.readthedocs.io/en/stable/lib/passlib.hash.sun_md5_crypt.html
29
+ */
30
+
31
+ #include "crypt-port.h"
32
+ #include "alg-md5.h"
33
+
34
+ #include <errno.h>
35
+ #include <stdlib.h>
36
+ #include <stdio.h>
37
+
38
+ #if INCLUDE_sunmd5
39
+
40
+ #define SUNMD5_PREFIX "$md5"
41
+ #define SUNMD5_PREFIX_LEN 4
42
+ #define SUNMD5_SALT_LEN 8
43
+ #define SUNMD5_MAX_SETTING_LEN 32 /* $md5,rounds=4294963199$12345678$ */
44
+ #define SUNMD5_BARE_OUTPUT_LEN 22 /* not counting the setting or the NUL */
45
+ #define SUNMD5_MAX_ROUNDS (0xFFFFFFFFul)
46
+
47
+ /* At each round of the algorithm, this string (including the trailing
48
+ NUL) may or may not be included in the input to MD5, depending on a
49
+ pseudorandom coin toss. It is Hamlet's famous soliloquy from the
50
+ play of the same name, which is in the public domain. Text from
51
+ <https://www.gutenberg.org/files/1524/old/2ws2610.tex> with double
52
+ blank lines replaced with `\n`. Note that more recent Project
53
+ Gutenberg editions of _Hamlet_ are punctuated differently. */
54
+ static const char hamlet_quotation[] =
55
+ "To be, or not to be,--that is the question:--\n"
56
+ "Whether 'tis nobler in the mind to suffer\n"
57
+ "The slings and arrows of outrageous fortune\n"
58
+ "Or to take arms against a sea of troubles,\n"
59
+ "And by opposing end them?--To die,--to sleep,--\n"
60
+ "No more; and by a sleep to say we end\n"
61
+ "The heartache, and the thousand natural shocks\n"
62
+ "That flesh is heir to,--'tis a consummation\n"
63
+ "Devoutly to be wish'd. To die,--to sleep;--\n"
64
+ "To sleep! perchance to dream:--ay, there's the rub;\n"
65
+ "For in that sleep of death what dreams may come,\n"
66
+ "When we have shuffled off this mortal coil,\n"
67
+ "Must give us pause: there's the respect\n"
68
+ "That makes calamity of so long life;\n"
69
+ "For who would bear the whips and scorns of time,\n"
70
+ "The oppressor's wrong, the proud man's contumely,\n"
71
+ "The pangs of despis'd love, the law's delay,\n"
72
+ "The insolence of office, and the spurns\n"
73
+ "That patient merit of the unworthy takes,\n"
74
+ "When he himself might his quietus make\n"
75
+ "With a bare bodkin? who would these fardels bear,\n"
76
+ "To grunt and sweat under a weary life,\n"
77
+ "But that the dread of something after death,--\n"
78
+ "The undiscover'd country, from whose bourn\n"
79
+ "No traveller returns,--puzzles the will,\n"
80
+ "And makes us rather bear those ills we have\n"
81
+ "Than fly to others that we know not of?\n"
82
+ "Thus conscience does make cowards of us all;\n"
83
+ "And thus the native hue of resolution\n"
84
+ "Is sicklied o'er with the pale cast of thought;\n"
85
+ "And enterprises of great pith and moment,\n"
86
+ "With this regard, their currents turn awry,\n"
87
+ "And lose the name of action.--Soft you now!\n"
88
+ "The fair Ophelia!--Nymph, in thy orisons\n"
89
+ "Be all my sins remember'd.\n";
90
+
91
+ /* Decide, pseudorandomly, whether or not to include the above quotation
92
+ in the input to MD5. */
93
+ static inline bool
94
+ get_nth_bit (const uint8_t digest[16], unsigned int n)
95
+ {
96
+ unsigned int byte = (n % 128) / 8;
97
+ unsigned int bit = (n % 128) % 8;
98
+ return !!(digest[byte] & (1 << bit));
99
+ }
100
+
101
+ static bool
102
+ muffet_coin_toss (const uint8_t prev_digest[16], unsigned int round_count)
103
+ {
104
+ unsigned int x, y, a, b, r, v, i;
105
+ for (i = 0, x = 0, y = 0; i < 8; i++)
106
+ {
107
+ a = prev_digest[(i + 0) % 16];
108
+ b = prev_digest[(i + 3) % 16];
109
+ r = a >> (b % 5);
110
+ v = prev_digest[r % 16];
111
+ if (b & (1u << (a % 8)))
112
+ v /= 2;
113
+ x |= ((unsigned int) +get_nth_bit (prev_digest, v)) << i;
114
+
115
+ a = prev_digest[(i + 8) % 16];
116
+ b = prev_digest[(i + 11) % 16];
117
+ r = a >> (b % 5);
118
+ v = prev_digest[r % 16];
119
+ if (b & (1u << (a % 8)))
120
+ v /= 2;
121
+ y |= ((unsigned int) +get_nth_bit (prev_digest, v)) << i;
122
+ }
123
+
124
+ if (get_nth_bit (prev_digest, round_count))
125
+ x /= 2;
126
+ if (get_nth_bit (prev_digest, round_count + 64))
127
+ y /= 2;
128
+
129
+ return !!(get_nth_bit (prev_digest, x) ^ get_nth_bit (prev_digest, y));
130
+ }
131
+
132
+ static inline void
133
+ write_itoa64_4 (uint8_t *output,
134
+ unsigned int b0, unsigned int b1, unsigned int b2)
135
+ {
136
+ unsigned int value = (b0 << 0) | (b1 << 8) | (b2 << 16);
137
+ output[0] = itoa64[value & 0x3f];
138
+ output[1] = itoa64[(value >> 6) & 0x3f];
139
+ output[2] = itoa64[(value >> 12) & 0x3f];
140
+ output[3] = itoa64[(value >> 18) & 0x3f];
141
+ }
142
+
143
+ /* used only for the last two bytes of crypt_sunmd5_rn output */
144
+ static inline void
145
+ write_itoa64_2 (uint8_t *output,
146
+ unsigned int b0, unsigned int b1, unsigned int b2)
147
+ {
148
+ unsigned int value = (b0 << 0) | (b1 << 8) | (b2 << 16);
149
+ output[0] = itoa64[value & 0x3f];
150
+ output[1] = itoa64[(value >> 6) & 0x3f];
151
+ }
152
+
153
+ /* Module entry points. */
154
+
155
+ void
156
+ crypt_sunmd5_rn (const char *phrase, size_t phr_size,
157
+ const char *setting, size_t ARG_UNUSED (set_size),
158
+ uint8_t *output, size_t out_size,
159
+ void *scratch, size_t scr_size)
160
+ {
161
+ struct crypt_sunmd5_scratch
162
+ {
163
+ MD5_CTX ctx;
164
+ uint8_t dg[16];
165
+ char rn[16];
166
+ };
167
+
168
+ /* If 'setting' doesn't start with the prefix, we should not have
169
+ been called in the first place. */
170
+ if (strncmp (setting, SUNMD5_PREFIX, SUNMD5_PREFIX_LEN)
171
+ || (setting[SUNMD5_PREFIX_LEN] != '$'
172
+ && setting[SUNMD5_PREFIX_LEN] != ','))
173
+ {
174
+ errno = EINVAL;
175
+ return;
176
+ }
177
+
178
+ /* For bug-compatibility with the original implementation, we allow
179
+ 'rounds=' to follow either '$md5,' or '$md5$'. */
180
+ const char *p = setting + SUNMD5_PREFIX_LEN + 1;
181
+ unsigned int nrounds = 4096;
182
+ if (!strncmp (p, "rounds=", sizeof "rounds=" - 1))
183
+ {
184
+ p += sizeof "rounds=" - 1;
185
+ /* Do not allow an explicit setting of zero additional rounds,
186
+ nor leading zeroes on the number of rounds. */
187
+ if (!(*p >= '1' && *p <= '9'))
188
+ {
189
+ errno = EINVAL;
190
+ return;
191
+ }
192
+
193
+ errno = 0;
194
+ char *endp;
195
+ unsigned long arounds = strtoul (p, &endp, 10);
196
+ if (endp == p || arounds > SUNMD5_MAX_ROUNDS || errno)
197
+ {
198
+ errno = EINVAL;
199
+ return;
200
+ }
201
+ nrounds += (unsigned int)arounds;
202
+ p = endp;
203
+ if (*p != '$')
204
+ {
205
+ errno = EINVAL;
206
+ return;
207
+ }
208
+ p += 1;
209
+ }
210
+
211
+ /* p now points to the beginning of the actual salt. */
212
+ p += strspn (p, (const char *)itoa64);
213
+ if (*p != '\0' && *p != '$')
214
+ {
215
+ errno = EINVAL;
216
+ return;
217
+ }
218
+ /* For bug-compatibility with the original implementation, if p
219
+ points to a '$' and the following character is either another '$'
220
+ or NUL, the first '$' should be included in the salt. */
221
+ if (p[0] == '$' && (p[1] == '$' || p[1] == '\0'))
222
+ p += 1;
223
+
224
+ size_t saltlen = (size_t) (p - setting);
225
+ /* Do we have enough space? */
226
+ if (scr_size < sizeof (struct crypt_sunmd5_scratch)
227
+ || out_size < saltlen + SUNMD5_BARE_OUTPUT_LEN + 2)
228
+ {
229
+ errno = ERANGE;
230
+ return;
231
+ }
232
+
233
+ struct crypt_sunmd5_scratch *s = scratch;
234
+
235
+ /* Initial round. */
236
+ MD5_Init (&s->ctx);
237
+ MD5_Update (&s->ctx, phrase, phr_size);
238
+ MD5_Update (&s->ctx, setting, saltlen);
239
+ MD5_Final (s->dg, &s->ctx);
240
+
241
+ /* Stretching rounds. */
242
+ for (unsigned int i = 0; i < nrounds; i++)
243
+ {
244
+ MD5_Init (&s->ctx);
245
+
246
+ MD5_Update (&s->ctx, s->dg, sizeof s->dg);
247
+
248
+ /* The trailing nul is intentionally included. */
249
+ if (muffet_coin_toss (s->dg, i))
250
+ MD5_Update (&s->ctx, hamlet_quotation, sizeof hamlet_quotation);
251
+
252
+ int nwritten = snprintf (s->rn, sizeof s->rn, "%u", i);
253
+ assert (nwritten >= 1 && (unsigned int)nwritten + 1 <= sizeof s->rn);
254
+ MD5_Update (&s->ctx, s->rn, (unsigned int)nwritten);
255
+
256
+ MD5_Final (s->dg, &s->ctx);
257
+ }
258
+
259
+ memcpy (output, setting, saltlen);
260
+ *(output + saltlen + 0) = '$';
261
+ /* This is the same permuted order used by BSD md5-crypt ($1$). */
262
+ write_itoa64_4 (output + saltlen + 1, s->dg[12], s->dg[ 6], s->dg[0]);
263
+ write_itoa64_4 (output + saltlen + 5, s->dg[13], s->dg[ 7], s->dg[1]);
264
+ write_itoa64_4 (output + saltlen + 9, s->dg[14], s->dg[ 8], s->dg[2]);
265
+ write_itoa64_4 (output + saltlen + 13, s->dg[15], s->dg[ 9], s->dg[3]);
266
+ write_itoa64_4 (output + saltlen + 17, s->dg[ 5], s->dg[10], s->dg[4]);
267
+ write_itoa64_2 (output + saltlen + 21, s->dg[11], 0, 0);
268
+ *(output + saltlen + 23) = '\0';
269
+ }
270
+
271
+ void
272
+ gensalt_sunmd5_rn (unsigned long count,
273
+ const uint8_t *rbytes,
274
+ size_t nrbytes,
275
+ uint8_t *output,
276
+ size_t o_size)
277
+ {
278
+ if (o_size < SUNMD5_MAX_SETTING_LEN + 1)
279
+ {
280
+ errno = ERANGE;
281
+ return;
282
+ }
283
+ if (nrbytes < 6 + 2)
284
+ {
285
+ errno = EINVAL;
286
+ return;
287
+ }
288
+
289
+ /* The default number of rounds, 4096, is much too low. The actual
290
+ number of rounds is somewhat randomized to make construction of
291
+ rainbow tables more difficult (effectively this means an extra 16
292
+ bits of entropy are smuggled into the salt via the round number). */
293
+ if (count < 32768)
294
+ count = 32768;
295
+ else if (count > SUNMD5_MAX_ROUNDS - 65536)
296
+ count = SUNMD5_MAX_ROUNDS - 65536;
297
+
298
+ count += ((unsigned long)rbytes[0]) << 8;
299
+ count += ((unsigned long)rbytes[1]) << 0;
300
+
301
+ assert (count != 0);
302
+
303
+ size_t written = (size_t) snprintf ((char *)output, o_size,
304
+ "%s,rounds=%lu$", SUNMD5_PREFIX, count);
305
+
306
+
307
+ write_itoa64_4(output + written + 0, rbytes[2], rbytes[3], rbytes[4]);
308
+ write_itoa64_4(output + written + 4, rbytes[5], rbytes[6], rbytes[7]);
309
+
310
+ output[written + 8] = '$';
311
+ output[written + 9] = '\0';
312
+ }
313
+
314
+ #endif