You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

catena.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. * Copyright 2024 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "catena.h"
  18. #include <sodium.h>
  19. #if __BYTE_ORDER == __LITTLE_ENDIAN
  20. #define TO_LITTLE_ENDIAN_64(n) (n)
  21. #define TO_LITTLE_ENDIAN_32(n) (n)
  22. #else
  23. #define TO_LITTLE_ENDIAN_64 GUINT64_SWAP_LE_BE
  24. #define TO_LITTLE_ENDIAN_32 GUINT32_SWAP_LE_BE
  25. #endif
  26. /* Recommended default values */
  27. #define H_LEN CATENA_HLEN
  28. #define KEY_LEN 16
  29. const uint8_t VERSION_ID[] = "Butterfly-Full";
  30. const uint8_t LAMBDA = 4;
  31. const uint8_t GARLIC = 16;
  32. const uint8_t MIN_GARLIC = 16;
  33. /*
  34. * Hash part
  35. */
  36. static inline void
  37. __Hash1(const uint8_t *input, const uint32_t inputlen,
  38. uint8_t hash[H_LEN])
  39. {
  40. crypto_generichash_blake2b_state ctx;
  41. crypto_generichash_blake2b_init(&ctx, NULL, 0, H_LEN);
  42. crypto_generichash_blake2b_update(&ctx, input, inputlen);
  43. crypto_generichash_blake2b_final(&ctx, hash, H_LEN);
  44. }
  45. /***************************************************/
  46. static inline void __Hash2(const uint8_t *i1, const uint8_t i1len, const uint8_t *i2,
  47. const uint8_t i2len, uint8_t hash[H_LEN])
  48. {
  49. crypto_generichash_blake2b_state ctx;
  50. crypto_generichash_blake2b_init(&ctx, NULL, 0, H_LEN);
  51. crypto_generichash_blake2b_update(&ctx, i1, i1len);
  52. crypto_generichash_blake2b_update(&ctx, i2, i2len);
  53. crypto_generichash_blake2b_final(&ctx, hash, H_LEN);
  54. }
  55. /***************************************************/
  56. static inline void __Hash3(const uint8_t *i1, const uint8_t i1len, const uint8_t *i2,
  57. const uint8_t i2len, const uint8_t *i3, const uint8_t i3len,
  58. uint8_t hash[H_LEN])
  59. {
  60. crypto_generichash_blake2b_state ctx;
  61. crypto_generichash_blake2b_init(&ctx, NULL, 0, H_LEN);
  62. crypto_generichash_blake2b_update(&ctx, i1, i1len);
  63. crypto_generichash_blake2b_update(&ctx, i2, i2len);
  64. crypto_generichash_blake2b_update(&ctx, i3, i3len);
  65. crypto_generichash_blake2b_final(&ctx, hash, H_LEN);
  66. }
  67. /***************************************************/
  68. static inline void __Hash4(const uint8_t *i1, const uint8_t i1len, const uint8_t *i2,
  69. const uint8_t i2len, const uint8_t *i3, const uint8_t i3len,
  70. const uint8_t *i4, const uint8_t i4len, uint8_t hash[H_LEN])
  71. {
  72. crypto_generichash_blake2b_state ctx;
  73. crypto_generichash_blake2b_init(&ctx, NULL, 0, H_LEN);
  74. crypto_generichash_blake2b_update(&ctx, i1, i1len);
  75. crypto_generichash_blake2b_update(&ctx, i2, i2len);
  76. crypto_generichash_blake2b_update(&ctx, i3, i3len);
  77. crypto_generichash_blake2b_update(&ctx, i4, i4len);
  78. crypto_generichash_blake2b_final(&ctx, hash, H_LEN);
  79. }
  80. /***************************************************/
  81. static inline void __Hash5(const uint8_t *i1, const uint8_t i1len, const uint8_t *i2,
  82. const uint8_t i2len, const uint8_t *i3, const uint8_t i3len,
  83. const uint8_t *i4, const uint8_t i4len, const uint8_t *i5,
  84. const uint8_t i5len, uint8_t hash[H_LEN])
  85. {
  86. crypto_generichash_blake2b_state ctx;
  87. crypto_generichash_blake2b_init(&ctx, NULL, 0, H_LEN);
  88. crypto_generichash_blake2b_update(&ctx, i1, i1len);
  89. crypto_generichash_blake2b_update(&ctx, i2, i2len);
  90. crypto_generichash_blake2b_update(&ctx, i3, i3len);
  91. crypto_generichash_blake2b_update(&ctx, i4, i4len);
  92. crypto_generichash_blake2b_update(&ctx, i5, i5len);
  93. crypto_generichash_blake2b_final(&ctx, hash, H_LEN);
  94. }
  95. static inline void
  96. __HashFast(int vindex, const uint8_t *i1, const uint8_t *i2,
  97. uint8_t hash[H_LEN])
  98. {
  99. __Hash2(i1, H_LEN, i2, H_LEN, hash);
  100. }
  101. static void __ResetState(void)
  102. {
  103. }
  104. /*
  105. * Misc utils
  106. */
  107. const uint8_t ZERO8[H_LEN] = {0};
  108. /* see: http://en.wikipedia.org/wiki/Xorshift#Variations */
  109. static int p;
  110. static uint64_t s[16];
  111. static void
  112. initXSState(const uint8_t *a, const uint8_t *b)
  113. {
  114. p = 0;
  115. for (int i = 0; i < 8; i++) {
  116. s[i] = UINT64_C(0);
  117. s[i + 8] = UINT64_C(0);
  118. for (int j = 0; j < 8; j++) {
  119. s[i] |= ((uint64_t) a[i * 8 + j]) << j * 8;
  120. s[i + 8] |= ((uint64_t) b[i * 8 + j]) << j * 8;
  121. }
  122. }
  123. }
  124. static uint64_t
  125. xorshift1024star(void)
  126. {
  127. uint64_t s0 = s[p];
  128. uint64_t s1 = s[p = (p + 1) & 15];
  129. s1 ^= s1 << 31;
  130. s1 ^= s1 >> 11;
  131. s0 ^= s0 >> 30;
  132. return (s[p] = s0 ^ s1) * UINT64_C(1181783497276652981);
  133. }
  134. static void
  135. H_INIT(const uint8_t *x, const uint16_t xlen, uint8_t *vm1, uint8_t *vm2)
  136. {
  137. const uint8_t l = 2;
  138. uint8_t *tmp = (uint8_t *) g_malloc(l * H_LEN);
  139. for (uint8_t i = 0; i != l; ++i) {
  140. __Hash2(&i, 1, x, xlen, tmp + i * H_LEN);
  141. }
  142. memcpy(vm1, tmp, H_LEN);
  143. memcpy(vm2, tmp + (l / 2 * H_LEN), H_LEN);
  144. g_free(tmp);
  145. }
  146. static void
  147. H_First(const uint8_t *i1, const uint8_t *i2, uint8_t *hash)
  148. {
  149. uint8_t i = 0;
  150. uint8_t *x = (uint8_t *) g_malloc(H_LEN);
  151. __ResetState();
  152. __Hash2(i1, H_LEN, i2, H_LEN, x);
  153. __Hash2(&i, 1, x, H_LEN, hash);
  154. g_free(x);
  155. }
  156. static inline void
  157. initmem(const uint8_t x[H_LEN], const uint64_t c, uint8_t *r)
  158. {
  159. uint8_t *vm2 = (uint8_t *) g_malloc(H_LEN);
  160. uint8_t *vm1 = (uint8_t *) g_malloc(H_LEN);
  161. H_INIT(x, H_LEN, vm1, vm2);
  162. __ResetState();
  163. __HashFast(0, vm1, vm2, r);
  164. __HashFast(1, r, vm1, r + H_LEN);
  165. /* Top row */
  166. for (uint64_t i = 2; i < c; i++) {
  167. __HashFast(i, r + (i - 1) * H_LEN, r + (i - 2) * H_LEN, r + i * H_LEN);
  168. }
  169. g_free(vm2);
  170. g_free(vm1);
  171. }
  172. static inline void
  173. catena_gamma(const uint8_t garlic, const uint8_t *salt,
  174. const uint8_t saltlen, uint8_t *r)
  175. {
  176. const uint64_t q = UINT64_C(1) << ((3 * garlic + 3) / 4);
  177. uint64_t i, j, j2;
  178. uint8_t *tmp = g_malloc(H_LEN);
  179. uint8_t *tmp2 = g_malloc(H_LEN);
  180. __Hash1(salt, saltlen, tmp);
  181. __Hash1(tmp, H_LEN, tmp2);
  182. initXSState(tmp, tmp2);
  183. __ResetState();
  184. for (i = 0; i < q; i++) {
  185. j = xorshift1024star() >> (64 - garlic);
  186. j2 = xorshift1024star() >> (64 - garlic);
  187. __HashFast(i, r + j * H_LEN, r + j2 * H_LEN, r + j * H_LEN);
  188. }
  189. g_free(tmp);
  190. g_free(tmp2);
  191. }
  192. static void
  193. XOR(const uint8_t *input1, const uint8_t *input2, uint8_t *output)
  194. {
  195. uint32_t i;
  196. for (i = 0; i < H_LEN; i++) {
  197. output[i] = input1[i] ^ input2[i];
  198. }
  199. }
  200. /*
  201. * Butterfly part
  202. */
  203. /*
  204. * Sigma function that defines the diagonal connections of a DBG
  205. * diagonal front: flip the (g-i)th bit (Inverse Butterfly Graph)
  206. * diagonal back: flip the i-(g-1)th bit (Regular Butterfly Graph)
  207. */
  208. static uint64_t
  209. sigma(const uint8_t g, const uint64_t i, const uint64_t j)
  210. {
  211. if (i < g) {
  212. return (j ^ (UINT64_C(1) << (g - 1 - i))); /* diagonal front */
  213. }
  214. else {
  215. return (j ^ (UINT64_C(1) << (i - (g - 1)))); /* diagonal back */
  216. }
  217. }
  218. /*calculate actual index from level and element index*/
  219. static uint64_t
  220. idx(uint64_t i, uint64_t j, uint8_t co, uint64_t c, uint64_t m)
  221. {
  222. i += co;
  223. if (i % 3 == 0) {
  224. return j;
  225. }
  226. else if (i % 3 == 1) {
  227. if (j < m) {
  228. /* still fits in the array */
  229. return j + c;
  230. }
  231. else {
  232. /* start overwriting elements at the beginning */
  233. return j - m;
  234. }
  235. }
  236. /* i % 3 == 2 */
  237. return j + m;
  238. }
  239. /*
  240. * Computes the hash of x using a Double Butterfly Graph,
  241. * that forms as (2^g,\lamba)-Superconcentrator
  242. */
  243. static void
  244. Flap(const uint8_t x[H_LEN], const uint8_t lambda, const uint8_t garlic,
  245. const uint8_t *salt, const uint8_t saltlen, uint8_t h[H_LEN])
  246. {
  247. const uint64_t c = UINT64_C(1) << garlic;
  248. const uint64_t m = UINT64_C(1) << (garlic - 1); /* 0.5 * 2^g */
  249. const uint32_t l = 2 * garlic;
  250. uint8_t *r = g_malloc((c + m) * H_LEN);
  251. uint8_t *tmp = g_malloc(H_LEN);
  252. uint64_t i, j;
  253. uint8_t k;
  254. uint8_t co = 0; /* carry over from last iteration */
  255. /* Top row */
  256. initmem(x, c, r);
  257. /*Gamma Function*/
  258. catena_gamma(garlic, salt, saltlen, r);
  259. /* DBH */
  260. for (k = 0; k < lambda; k++) {
  261. for (i = 1; i < l; i++) {
  262. XOR(r + idx(i - 1, c - 1, co, c, m) * H_LEN,
  263. r + idx(i - 1, 0, co, c, m) * H_LEN, tmp);
  264. /*
  265. * r0 := H(tmp || vsigma(g,i-1,0) )
  266. * __Hash2(tmp, H_LEN, r+idx(i-1,sigma(garlic,i-1,0),co,c,m) * H_LEN, H_LEN,
  267. * r+idx(i,0,co,c,m) *H_LEN);
  268. */
  269. H_First(tmp,
  270. r + idx(i - 1, sigma(garlic, i - 1, 0), co, c, m) * H_LEN,
  271. r + idx(i, 0, co, c, m) * H_LEN);
  272. __ResetState();
  273. /* vertices */
  274. for (j = 1; j < c; j++) {
  275. /* tmp:= rj-1 XOR vj */
  276. XOR(r + idx(i, j - 1, co, c, m) * H_LEN,
  277. r + idx(i - 1, j, co, c, m) * H_LEN, tmp);
  278. /* rj := H(tmp || vsigma(g,i-1,j)) */
  279. __HashFast(j, tmp,
  280. r + idx(i - 1, sigma(garlic, i - 1, j), co, c, m) * H_LEN,
  281. r + idx(i, j, co, c, m) * H_LEN);
  282. }
  283. }
  284. co = (co + (i - 1)) % 3;
  285. }
  286. memcpy(h, r + idx(0, c - 1, co, c, m) * H_LEN, H_LEN);
  287. g_free(r);
  288. g_free(tmp);
  289. }
  290. static int
  291. __Catena(const uint8_t *pwd, const uint32_t pwdlen,
  292. const uint8_t *salt, const uint8_t saltlen, const uint8_t *data,
  293. const uint32_t datalen, const uint8_t lambda, const uint8_t min_garlic,
  294. const uint8_t garlic, const uint8_t hashlen, const uint8_t client,
  295. const uint8_t tweak_id, uint8_t *hash)
  296. {
  297. uint8_t x[H_LEN];
  298. uint8_t hv[H_LEN];
  299. uint8_t t[4];
  300. uint8_t c;
  301. if ((hashlen > H_LEN) || (garlic > 63) || (min_garlic > garlic) || (lambda == 0) || (min_garlic == 0)) {
  302. return -1;
  303. }
  304. /*Compute H(V)*/
  305. __Hash1(VERSION_ID, strlen((char *) VERSION_ID), hv);
  306. /* Compute Tweak */
  307. t[0] = tweak_id;
  308. t[1] = lambda;
  309. t[2] = hashlen;
  310. t[3] = saltlen;
  311. /* Compute H(AD) */
  312. __Hash1((uint8_t *) data, datalen, x);
  313. /* Compute the initial value to hash */
  314. __Hash5(hv, H_LEN, t, 4, x, H_LEN, pwd, pwdlen, salt, saltlen, x);
  315. /*Overwrite Password if enabled*/
  316. #ifdef OVERWRITE
  317. erasepwd(pwd, pwdlen);
  318. #endif
  319. Flap(x, lambda, (min_garlic + 1) / 2, salt, saltlen, x);
  320. for (c = min_garlic; c <= garlic; c++) {
  321. Flap(x, lambda, c, salt, saltlen, x);
  322. if ((c == garlic) && (client == CLIENT)) {
  323. memcpy(hash, x, H_LEN);
  324. return 0;
  325. }
  326. __Hash2(&c, 1, x, H_LEN, x);
  327. memset(x + hashlen, 0, H_LEN - hashlen);
  328. }
  329. memcpy(hash, x, hashlen);
  330. return 0;
  331. }
  332. /***************************************************/
  333. int catena(const uint8_t *pwd, const uint32_t pwdlen, const uint8_t *salt,
  334. const uint8_t saltlen, const uint8_t *data, const uint32_t datalen,
  335. const uint8_t lambda, const uint8_t min_garlic, const uint8_t garlic,
  336. const uint8_t hashlen, uint8_t *hash)
  337. {
  338. return __Catena(pwd, pwdlen, salt, saltlen, data, datalen, lambda,
  339. min_garlic, garlic, hashlen, REGULAR, PASSWORD_HASHING_MODE, hash);
  340. }
  341. int simple_catena(const uint8_t *pwd, const uint32_t pwdlen,
  342. const uint8_t *salt, const uint8_t saltlen,
  343. const uint8_t *data, const uint32_t datalen,
  344. uint8_t hash[H_LEN])
  345. {
  346. return __Catena(pwd, pwdlen, salt, saltlen, data, datalen,
  347. LAMBDA, MIN_GARLIC, GARLIC, H_LEN,
  348. REGULAR, PASSWORD_HASHING_MODE, hash);
  349. }
  350. int catena_test(void)
  351. {
  352. /* From catena-v3.1 spec */
  353. uint8_t pw[] = {0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64};
  354. uint8_t salt[] = {0x73, 0x61, 0x6c, 0x74};
  355. uint8_t ad[] = {0x64, 0x61, 0x74, 0x61};
  356. uint8_t expected[] = {
  357. 0x20, 0xc5, 0x91, 0x93, 0x8f, 0xc3, 0xaf, 0xcc, 0x3b, 0xba, 0x91, 0xd2, 0xfb,
  358. 0x84, 0xbf, 0x7b, 0x44, 0x04, 0xf9, 0x4c, 0x45, 0xed, 0x4d, 0x11, 0xa7, 0xe2,
  359. 0xb4, 0x12, 0x3e, 0xab, 0x0b, 0x77, 0x4a, 0x12, 0xb4, 0x22, 0xd0, 0xda, 0xb5,
  360. 0x25, 0x29, 0x02, 0xfc, 0x54, 0x47, 0xea, 0x82, 0x63, 0x8c, 0x1a, 0xfb, 0xa7,
  361. 0xa9, 0x94, 0x24, 0x13, 0x0e, 0x44, 0x36, 0x3b, 0x9d, 0x9f, 0xc9, 0x60};
  362. uint8_t real[H_LEN];
  363. if (catena(pw, sizeof(pw), salt, sizeof(salt), ad, sizeof(ad),
  364. 4, 10, 10, H_LEN, real) != 0) {
  365. return -1;
  366. }
  367. return memcmp(real, expected, H_LEN);
  368. }