dcblake2.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. {
  2. BLAKE2 reference source code package - reference C implementations
  3. Written in 2012 by Samuel Neves <[email protected]>
  4. Pascal tranlastion in 2014-2020 by Alexander Koblov ([email protected])
  5. To the extent possible under law, the author(s) have dedicated all copyright
  6. and related and neighboring rights to this software to the public domain
  7. worldwide. This software is distributed without any warranty.
  8. You should have received a copy of the CC0 Public Domain Dedication along with
  9. this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
  10. }
  11. unit DCblake2;
  12. {$mode objfpc}{$H+}
  13. {$macro on}{$R-}{$Q-}
  14. {$define USE_MTPROCS}
  15. interface
  16. uses
  17. SysUtils, CTypes;
  18. const
  19. BLAKE2S_BLOCKBYTES = 64;
  20. BLAKE2S_OUTBYTES = 32;
  21. BLAKE2S_KEYBYTES = 32;
  22. BLAKE2S_SALTBYTES = 8;
  23. BLAKE2S_PERSONALBYTES = 8;
  24. BLAKE2S_PARALLELISM_DEGREE = 8;
  25. const
  26. BLAKE2B_BLOCKBYTES = 128;
  27. BLAKE2B_OUTBYTES = 64;
  28. BLAKE2B_KEYBYTES = 64;
  29. BLAKE2B_SALTBYTES = 16;
  30. BLAKE2B_PERSONALBYTES = 16;
  31. BLAKE2B_PARALLELISM_DEGREE = 4;
  32. type
  33. {$packrecords 1}
  34. Pblake2s_param = ^blake2s_param;
  35. blake2s_param = record
  36. digest_length: cuint8; // 1
  37. key_length: cuint8; // 2
  38. fanout: cuint8; // 3
  39. depth: cuint8; // 4
  40. leaf_length: cuint32; // 8
  41. node_offset: array[0..5] of cuint8;// 14
  42. node_depth: cuint8; // 15
  43. inner_length: cuint8; // 16
  44. // uint8_t reserved[0];
  45. salt: array[0..Pred(BLAKE2S_SALTBYTES)] of cuint8; // 24
  46. personal: array[0..Pred(BLAKE2S_PERSONALBYTES)] of cuint8; // 32
  47. end;
  48. {$packrecords 8}
  49. Pblake2s_state = ^blake2s_state;
  50. blake2s_state = record
  51. h: array[0..7] of cuint32;
  52. t: array[0..1] of cuint32;
  53. f: array[0..1] of cuint32;
  54. buf: array[0..Pred(2 * BLAKE2S_BLOCKBYTES)] of cuint8;
  55. buflen: csize_t;
  56. last_node: cuint8;
  57. end;
  58. {$packrecords 1}
  59. Pblake2sp_state = ^blake2sp_state;
  60. blake2sp_state = record
  61. S: array[0..7] of blake2s_state;
  62. R: blake2s_state;
  63. buf: array[0..Pred(8 * BLAKE2S_BLOCKBYTES)] of cuint8;
  64. buflen: csize_t;
  65. inlen: csize_t;
  66. inp: PByte;
  67. end;
  68. {$packrecords c}
  69. Pblake2b_state = ^blake2b_state;
  70. blake2b_state = record
  71. h: array[0..7] of cuint64;
  72. t: array[0..1] of cuint64;
  73. f: array[0..1] of cuint64;
  74. buf: array [0..Pred(BLAKE2B_BLOCKBYTES)] of cuint8;
  75. buflen: csize_t;
  76. outlen: csize_t;
  77. last_node: cuint8;
  78. end;
  79. {$packrecords 1}
  80. Pblake2b_param = ^blake2b_param;
  81. blake2b_param = record
  82. digest_length: uint8; // 1
  83. key_length: cuint8; // 2
  84. fanout: cuint8; // 3
  85. depth: cuint8; // 4
  86. leaf_length: cuint32; // 8
  87. node_offset: cuint32; // 12
  88. xof_length: cuint32; // 16
  89. node_depth: cuint8; // 17
  90. inner_length: cuint8; // 18
  91. reserved: array[0..13] of cuint8; // 32
  92. salt: array [0..Pred(BLAKE2B_SALTBYTES)] of cuint8; // 48
  93. personal: array[0..Pred(BLAKE2B_PERSONALBYTES)] of cuint8; // 64
  94. end;
  95. {$packrecords default}
  96. Pblake2bp_state = ^blake2bp_state;
  97. blake2bp_state = record
  98. S: array[0..3] of blake2b_state;
  99. R: blake2b_state;
  100. buf: array[0..Pred(4 * BLAKE2B_BLOCKBYTES)] of cuint8;
  101. buflen: csize_t;
  102. outlen: csize_t;
  103. inlen: csize_t;
  104. inp: PByte;
  105. end;
  106. function blake2s_init( S: Pblake2s_state; const outlen: cuint8 ): cint;
  107. function blake2s_update( S: Pblake2s_state; inp: pcuint8; inlen: cuint64 ): cint;
  108. function blake2s_final( S: Pblake2s_state; outp: pcuint8; outlen: cuint8 ): cint;
  109. function blake2sp_init( S: Pblake2sp_state; const outlen: cuint8 ): cint;
  110. function blake2sp_update( S: Pblake2sp_state; inp: pcuint8; inlen: cuint64 ): cint;
  111. function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
  112. function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
  113. function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
  114. function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
  115. function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
  116. function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
  117. function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
  118. implementation
  119. {$IF DEFINED(USE_MTPROCS)}
  120. uses
  121. MTProcs
  122. {$IF DEFINED(CPUX86_64)}
  123. , CPU
  124. {$ENDIF}
  125. ;
  126. {$ELSE}
  127. {$IF DEFINED(CPUX86_64)}
  128. uses
  129. CPU;
  130. {$ENDIF}
  131. type
  132. TMultiThreadProcItem = Pointer;
  133. {$ENDIF}
  134. const blake2s_IV: array[0..7] of cuint32 =
  135. (
  136. $6A09E667, $BB67AE85, $3C6EF372, $A54FF53A,
  137. $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19
  138. );
  139. const blake2b_IV: array[0..7] of cint64 =
  140. (
  141. $6a09e667f3bcc908, $bb67ae8584caa73b,
  142. $3c6ef372fe94f82b, $a54ff53a5f1d36f1,
  143. $510e527fade682d1, $9b05688c2b3e6c1f,
  144. $1f83d9abfb41bd6b, $5be0cd19137e2179
  145. );
  146. function load32( const src: Pointer ): cuint32; inline;
  147. begin
  148. Result := NtoLE(pcuint32(src)^);
  149. end;
  150. function load64( const src: pointer ): cuint64; inline;
  151. begin
  152. Result := NtoLE(pcuint64(src)^);
  153. end;
  154. procedure store32( dst: pointer; w: cuint32 ); inline;
  155. begin
  156. pcuint32(dst)^ := LEtoN(w);
  157. end;
  158. procedure store64( dst: pointer; w: cuint64 ); inline;
  159. begin
  160. pcuint64(dst)^ := LEtoN(w);
  161. end;
  162. function load48( const src: pointer ): cuint64; inline;
  163. var
  164. w: cuint64;
  165. p: pcuint8;
  166. begin
  167. p := pcuint8(src);
  168. w := p^; Inc(p);
  169. w := w or cuint64( p^ ) shl 8; inc(p);
  170. w := w or cuint64( p^ ) shl 16; inc(p);
  171. w := w or cuint64( p^ ) shl 24; inc(p);
  172. w := w or cuint64( p^ ) shl 32; inc(p);
  173. w := w or cuint64( p^ ) shl 40; inc(p);
  174. Result := w;
  175. end;
  176. procedure store48( dst: pointer; w: cuint64 ); inline;
  177. var
  178. p: pcuint8;
  179. begin
  180. p := pcuint8(dst);
  181. p^ := cuint8(w); w := w shr 8; inc(p);
  182. p^ := cuint8(w); w := w shr 8; inc(p);
  183. p^ := cuint8(w); w := w shr 8; inc(p);
  184. p^ := cuint8(w); w := w shr 8; inc(p);
  185. p^ := cuint8(w); w := w shr 8; inc(p);
  186. p^ := cuint8(w); inc(p);
  187. end;
  188. var
  189. blake2s_compress: function(S: Pblake2s_state; const block: pcuint8): cint;
  190. blake2b_compress: procedure(S: Pblake2b_state; const block: pcuint8);
  191. {$IF DEFINED(CPUX86_64)}
  192. {$include blake2_sse.inc}
  193. {$include blake2_avx.inc}
  194. {$ELSE}
  195. {$include blake2_pas.inc}
  196. {$ENDIF}
  197. function blake2s_set_lastnode( S: Pblake2s_state ): cint; inline;
  198. begin
  199. S^.f[1] := $FFFFFFFF;
  200. Result := 0;
  201. end;
  202. function blake2s_clear_lastnode( S: Pblake2s_state ): cint; inline;
  203. begin
  204. S^.f[1] := 0;
  205. Result := 0;
  206. end;
  207. //* Some helper functions, not necessarily useful */
  208. function blake2s_set_lastblock( S: Pblake2s_state ): cint; inline;
  209. begin
  210. if( S^.last_node <> 0 ) then blake2s_set_lastnode( S );
  211. S^.f[0] := $FFFFFFFF;
  212. Result := 0;
  213. end;
  214. function blake2s_clear_lastblock( S: Pblake2s_state ): cint; inline;
  215. begin
  216. if( S^.last_node <> 0 ) then blake2s_clear_lastnode( S );
  217. S^.f[0] := 0;
  218. Result := 0;
  219. end;
  220. function blake2s_increment_counter( S: Pblake2s_state; const inc: cuint32 ): cint; inline;
  221. begin
  222. S^.t[0] += inc;
  223. S^.t[1] += cuint32( S^.t[0] < inc );
  224. Result := 0;
  225. end;
  226. function blake2s_init0( S: Pblake2s_state ): cint; inline;
  227. var
  228. i: cint;
  229. begin
  230. FillChar( S^, sizeof( blake2s_state ), 0 );
  231. for i := 0 to 8 - 1 do S^.h[i] := blake2s_IV[i];
  232. Result := 0;
  233. end;
  234. //* init2 xors IV with input parameter block */
  235. function blake2s_init_param( S: Pblake2s_state; const P: Pblake2s_param ): cint;
  236. var
  237. i: csize_t;
  238. pp: pcuint32;
  239. begin
  240. blake2s_init0( S );
  241. pp := pcuint32( P );
  242. //* IV XOR ParamBlock */
  243. // for i := 0; i < 8; ++i )
  244. for i := 0 to 8 - 1 do
  245. S^.h[i] := S^.h[i] xor load32( @pp[i] );
  246. Result := 0;
  247. end;
  248. // Sequential blake2s initialization
  249. function blake2s_init( S: Pblake2s_state; const outlen: cuint8 ): cint;
  250. var
  251. P: blake2s_param;
  252. begin
  253. //* Move interval verification here? */
  254. if ( ( outlen = 0 ) or ( outlen > BLAKE2S_OUTBYTES ) ) then Exit(-1);
  255. P.digest_length := outlen;
  256. P.key_length := 0;
  257. P.fanout := 1;
  258. P.depth := 1;
  259. store32( @P.leaf_length, 0 );
  260. store48( @P.node_offset, 0 );
  261. P.node_depth := 0;
  262. P.inner_length := 0;
  263. // memset(P^.reserved, 0, sizeof(P^.reserved) );
  264. FillChar( P.salt, sizeof( P.salt ), 0 );
  265. FillChar( P.personal, sizeof( P.personal ), 0 );
  266. Result := blake2s_init_param( S, @P );
  267. end;
  268. function blake2s_update( S: Pblake2s_state; inp: pcuint8; inlen: cuint64 ): cint;
  269. var
  270. left, fill: csize_t;
  271. begin
  272. while( inlen > 0 ) do
  273. begin
  274. left := S^.buflen;
  275. fill := 2 * BLAKE2S_BLOCKBYTES - left;
  276. if( inlen > fill ) then
  277. begin
  278. Move( inp^, S^.buf[left], fill ); // Fill buffer
  279. S^.buflen += fill;
  280. blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
  281. blake2s_compress( S, S^.buf ); // Compress
  282. Move( S^.buf[BLAKE2S_BLOCKBYTES], S^.buf, BLAKE2S_BLOCKBYTES ); // Shift buffer left
  283. S^.buflen -= BLAKE2S_BLOCKBYTES;
  284. inp += fill;
  285. inlen -= fill;
  286. end
  287. else // inlen <= fill
  288. begin
  289. Move( inp^, S^.buf [left], inlen );
  290. S^.buflen += inlen; // Be lazy, do not compress
  291. inp += inlen;
  292. inlen -= inlen;
  293. end;
  294. end;
  295. Result := 0;
  296. end;
  297. function blake2s_final( S: Pblake2s_state; outp: pcuint8; outlen: cuint8 ): cint;
  298. var
  299. i: cint;
  300. buffer: array[0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
  301. begin
  302. if( S^.buflen > BLAKE2S_BLOCKBYTES ) then
  303. begin
  304. blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
  305. blake2s_compress( S, S^.buf);
  306. S^.buflen -= BLAKE2S_BLOCKBYTES;
  307. Move( S^.buf[BLAKE2S_BLOCKBYTES], S^.buf, S^.buflen );
  308. end;
  309. blake2s_increment_counter( S, cuint32(S^.buflen) );
  310. blake2s_set_lastblock( S );
  311. FillChar( S^.buf[S^.buflen], 2 * BLAKE2S_BLOCKBYTES - S^.buflen, 0 ); //* Padding */
  312. blake2s_compress( S, S^.buf );
  313. for i := 0 to 7 do //* Output full hash to temp buffer */
  314. store32( @buffer[sizeof( S^.h[i] ) * i], S^.h[i] );
  315. Move( buffer, outp^, outlen );
  316. Result := 0;
  317. end;
  318. function blake2sp_init_leaf(S: Pblake2s_state; outlen: cuint8; keylen: cuint8; offset: cuint64):cint; inline;
  319. var
  320. P: blake2s_param;
  321. begin
  322. P.digest_length := outlen;
  323. P.key_length := keylen;
  324. P.fanout := BLAKE2S_PARALLELISM_DEGREE;
  325. P.depth := 2;
  326. store32( @P.leaf_length, 0 );
  327. store48( @P.node_offset[0], offset );
  328. P.node_depth := 0;
  329. P.inner_length := BLAKE2S_OUTBYTES;
  330. FillChar( P.salt, sizeof( P.salt ), 0 );
  331. FillChar( P.personal, sizeof( P.personal ), 0 );
  332. Result:= blake2s_init_param( S, @P );
  333. end;
  334. function blake2sp_init_root( S: Pblake2s_state; outlen: cuint8; keylen: cuint8 ): cint; inline;
  335. var
  336. P: blake2s_param;
  337. begin
  338. P.digest_length := outlen;
  339. P.key_length := keylen;
  340. P.fanout := BLAKE2S_PARALLELISM_DEGREE;
  341. P.depth := 2;
  342. store32( @P.leaf_length, 0 );
  343. store48( @P.node_offset[0], 0 );
  344. P.node_depth := 1;
  345. P.inner_length := BLAKE2S_OUTBYTES;
  346. FillChar( P.salt, sizeof( P.salt ), 0 );
  347. FillChar( P.personal, sizeof( P.personal ), 0 );
  348. Result:= blake2s_init_param( S, @P );
  349. end;
  350. function blake2sp_init( S: Pblake2sp_state; const outlen: cuint8 ): cint;
  351. var
  352. i: csize_t;
  353. begin
  354. if (outlen = 0) or (outlen > BLAKE2S_OUTBYTES) then Exit(-1);
  355. FillChar( S^.buf, sizeof( S^.buf ), 0 );
  356. S^.buflen := 0;
  357. if( blake2sp_init_root( @S^.R, outlen, 0 ) < 0 ) then Exit(-1);
  358. for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
  359. if ( blake2sp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
  360. S^.R.last_node := 1;
  361. S^.S[BLAKE2S_PARALLELISM_DEGREE - 1].last_node := 1;
  362. Result := 0;
  363. end;
  364. procedure MTProcedure(id__: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
  365. var
  366. in__: pcuint8;
  367. inlen__: cuint64;
  368. S: Pblake2sp_state absolute Data;
  369. begin
  370. in__ := S^.inp;
  371. inlen__ := S^.inlen;
  372. in__ += id__ * BLAKE2S_BLOCKBYTES;
  373. while ( inlen__ >= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) do
  374. begin
  375. blake2s_update( @S^.S[id__], in__, BLAKE2S_BLOCKBYTES );
  376. in__ += BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
  377. inlen__ -= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
  378. end;
  379. end;
  380. function blake2sp_update( S: Pblake2sp_state; inp: pcuint8; inlen: cuint64 ): cint;
  381. var
  382. i, left, fill: csize_t;
  383. begin
  384. left := S^.buflen;
  385. fill := sizeof( S^.buf ) - left;
  386. if ( left <> 0) and (inlen >= fill ) then
  387. begin
  388. Move(inp^, S^.buf[left], fill);
  389. for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
  390. blake2s_update( @S^.S[i], @S^.buf[ i * BLAKE2S_BLOCKBYTES], BLAKE2S_BLOCKBYTES );
  391. inp += fill;
  392. inlen -= fill;
  393. left := 0;
  394. end;
  395. S^.inp := inp;
  396. S^.inlen := inlen;
  397. {$IF DEFINED(USE_MTPROCS)}
  398. ProcThreadPool.DoParallel(@MTProcedure, 0, BLAKE2S_PARALLELISM_DEGREE - 1, S);
  399. {$ELSE}
  400. for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do MTProcedure(i, S, nil);
  401. {$ENDIF}
  402. inp += inlen - inlen mod ( BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
  403. inlen := inlen mod (BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES);
  404. if ( inlen > 0 ) then
  405. Move(inp^, S^.buf[left], inlen );
  406. S^.buflen := left + inlen;
  407. Result := 0;
  408. end;
  409. function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
  410. var
  411. i, left: csize_t;
  412. hash: array[0..Pred(BLAKE2S_PARALLELISM_DEGREE), 0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
  413. begin
  414. for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
  415. begin
  416. if ( S^.buflen > i * BLAKE2S_BLOCKBYTES ) then
  417. begin
  418. left := S^.buflen - i * BLAKE2S_BLOCKBYTES;
  419. if ( left > BLAKE2S_BLOCKBYTES ) then left := BLAKE2S_BLOCKBYTES;
  420. blake2s_update( @S^.S[i], @S^.buf[i * BLAKE2S_BLOCKBYTES], left );
  421. end;
  422. blake2s_final( @S^.S[i], hash[i], BLAKE2S_OUTBYTES );
  423. end;
  424. for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
  425. blake2s_update( @S^.R, hash[i], BLAKE2S_OUTBYTES );
  426. blake2s_final( @S^.R, outp, outlen );
  427. Result := 0;
  428. end;
  429. procedure blake2b_set_lastnode( S: Pblake2b_state ); inline;
  430. begin
  431. S^.f[1] := cuint64(-1);
  432. end;
  433. //* Some helper functions, not necessarily useful */
  434. function blake2b_is_lastblock( S: Pblake2b_state ): cint; inline;
  435. begin
  436. Result := cint(S^.f[0] <> 0);
  437. end;
  438. procedure blake2b_set_lastblock( S: Pblake2b_state );
  439. begin
  440. if( S^.last_node <> 0 ) then blake2b_set_lastnode( S );
  441. S^.f[0] := cuint64(-1);
  442. end;
  443. procedure blake2b_increment_counter( S: Pblake2b_state; const inc: cuint64 );
  444. begin
  445. S^.t[0] += inc;
  446. S^.t[1] += cuint64( S^.t[0] < inc );
  447. end;
  448. procedure blake2b_init0( S: Pblake2b_state );
  449. var
  450. i: csize_t;
  451. begin
  452. fillchar( S^, sizeof( blake2b_state ), 0 );
  453. for i := 0 to 7 do S^.h[i] := cuint64(blake2b_IV[i]);
  454. end;
  455. //* init xors IV with input parameter block */
  456. function blake2b_init_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
  457. var
  458. i: csize_t;
  459. pp: pcuint8;
  460. begin
  461. pp := pcuint8( P );
  462. blake2b_init0( S );
  463. //* IV XOR ParamBlock */
  464. for i := 0 to 7 do
  465. S^.h[i] := S^.h[i] xor load64( pp + sizeof( S^.h[i] ) * i );
  466. S^.outlen := P^.digest_length;
  467. Result := 0;
  468. end;
  469. function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
  470. var
  471. P: blake2b_param;
  472. begin
  473. if ( ( outlen = 0 ) or ( outlen > BLAKE2B_OUTBYTES ) ) then Exit(-1);
  474. P.digest_length := cuint8(outlen);
  475. P.key_length := 0;
  476. P.fanout := 1;
  477. P.depth := 1;
  478. store32( @P.leaf_length, 0 );
  479. store32( @P.node_offset, 0 );
  480. store32( @P.xof_length, 0 );
  481. P.node_depth := 0;
  482. P.inner_length := 0;
  483. fillchar( P.reserved, sizeof( P.reserved ), 0 );
  484. fillchar( P.salt, sizeof( P.salt ), 0 );
  485. fillchar( P.personal, sizeof( P.personal ), 0 );
  486. Result := blake2b_init_param( S, @P );
  487. end;
  488. function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
  489. var
  490. left, fill: csize_t;
  491. begin
  492. if ( inlen > 0 ) then
  493. begin
  494. left := S^.buflen;
  495. fill := BLAKE2B_BLOCKBYTES - left;
  496. if ( inlen > fill ) then
  497. begin
  498. S^.buflen := 0;
  499. Move( pin^, S^.buf[left], fill ); //* Fill buffer */
  500. blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
  501. blake2b_compress( S, S^.buf ); //* Compress */
  502. pin += fill; inlen -= fill;
  503. while (inlen > BLAKE2B_BLOCKBYTES) do
  504. begin
  505. blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
  506. blake2b_compress( S, pin );
  507. pin += BLAKE2B_BLOCKBYTES;
  508. inlen -= BLAKE2B_BLOCKBYTES;
  509. end
  510. end;
  511. Move( pin^, S^.buf[S^.buflen], inlen );
  512. S^.buflen += inlen;
  513. end;
  514. Result := 0;
  515. end;
  516. function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
  517. var
  518. i: csize_t;
  519. buffer: array[0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
  520. begin
  521. if( pout = nil) or (outlen < S^.outlen ) then
  522. Exit(-1);
  523. if ( blake2b_is_lastblock( S ) <> 0 ) then
  524. Exit(-1);
  525. fillchar(buffer[0], BLAKE2B_OUTBYTES, 0);
  526. blake2b_increment_counter( S, S^.buflen );
  527. blake2b_set_lastblock( S );
  528. fillchar( S^.buf[S^.buflen], BLAKE2B_BLOCKBYTES - S^.buflen, 0 ); //* Padding */
  529. blake2b_compress( S, S^.buf );
  530. for i := 0 to 7 do //* Output full hash to temp buffer */
  531. store64( @buffer[sizeof( S^.h[i] ) * i], S^.h[i] );
  532. move( buffer[0], pout^, S^.outlen );
  533. fillchar(buffer[0], sizeof(buffer), 0);
  534. Result := 0;
  535. end;
  536. function blake2bp_init_leaf_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
  537. begin
  538. Result:= blake2b_init_param(S, P);
  539. S^.outlen := P^.inner_length;
  540. end;
  541. function blake2bp_init_leaf( S: Pblake2b_state; outlen, keylen: csize_t; offset: cuint64 ): cint;
  542. var
  543. P: blake2b_param;
  544. begin
  545. P.digest_length := cuint8(outlen);
  546. P.key_length := cuint8(keylen);
  547. P.fanout := BLAKE2B_PARALLELISM_DEGREE;
  548. P.depth := 2;
  549. store32( @P.leaf_length, 0 );
  550. store32( @P.node_offset, offset );
  551. store32( @P.xof_length, 0 );
  552. P.node_depth := 0;
  553. P.inner_length := BLAKE2B_OUTBYTES;
  554. FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
  555. FillChar( P.salt[0], sizeof( P.salt ), 0 );
  556. FillChar( P.personal[0], sizeof( P.personal ), 0 );
  557. Result:= blake2bp_init_leaf_param( S, @P );
  558. end;
  559. function blake2bp_init_root( S: Pblake2b_state; outlen, keylen: csize_t ): cint;
  560. var
  561. P: blake2b_param;
  562. begin
  563. P.digest_length := cuint8(outlen);
  564. P.key_length := cuint8(keylen);
  565. P.fanout := BLAKE2B_PARALLELISM_DEGREE;
  566. P.depth := 2;
  567. store32( @P.leaf_length, 0 );
  568. store32( @P.node_offset, 0 );
  569. store32( @P.xof_length, 0 );
  570. P.node_depth := 1;
  571. P.inner_length := BLAKE2B_OUTBYTES;
  572. FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
  573. FillChar( P.salt[0], sizeof( P.salt ), 0 );
  574. FillChar( P.personal[0], sizeof( P.personal ), 0 );
  575. Result:= blake2b_init_param( S, @P );
  576. end;
  577. function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
  578. var
  579. i: csize_t;
  580. begin
  581. if (outlen = 0) or (outlen > BLAKE2B_OUTBYTES) then Exit(-1);
  582. FillChar( S^.buf[0], sizeof( S^.buf ), 0 );
  583. S^.buflen := 0;
  584. S^.outlen := outlen;
  585. if( blake2bp_init_root( @S^.R, outlen, 0 ) < 0 ) then
  586. Exit(-1);
  587. for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
  588. if ( blake2bp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
  589. S^.R.last_node := 1;
  590. S^.S[BLAKE2B_PARALLELISM_DEGREE - 1].last_node := 1;
  591. Result:= 0;
  592. end;
  593. procedure blake2bp_MTProcedure(i: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
  594. var
  595. in__: pcuint8;
  596. inlen__: cuint64;
  597. S: Pblake2bp_state absolute Data;
  598. begin
  599. in__ := S^.inp;
  600. inlen__ := S^.inlen;
  601. in__ += i * BLAKE2B_BLOCKBYTES;
  602. while ( inlen__ >= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ) do
  603. begin
  604. blake2b_update( @S^.S[i], in__, BLAKE2B_BLOCKBYTES );
  605. in__ += BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
  606. inlen__ -= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
  607. end;
  608. end;
  609. function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
  610. var
  611. left, fill, i: csize_t;
  612. begin
  613. left := S^.buflen;
  614. fill := sizeof( S^.buf ) - left;
  615. if( left > 0) and (inlen >= fill ) then
  616. begin
  617. Move( inp^, S^.buf[left], fill );
  618. for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
  619. blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], BLAKE2B_BLOCKBYTES );
  620. inp += fill;
  621. inlen -= fill;
  622. left := 0;
  623. end;
  624. S^.inp := inp;
  625. S^.inlen := inlen;
  626. {$IF DEFINED(USE_MTPROCS)}
  627. ProcThreadPool.DoParallel(@blake2bp_MTProcedure, 0, BLAKE2B_PARALLELISM_DEGREE - 1, S);
  628. {$ELSE}
  629. for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do blake2bp_MTProcedure(i, S, nil);
  630. {$ENDIF}
  631. inp += inlen - inlen mod ( BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
  632. inlen := inlen mod (BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES);
  633. if ( inlen > 0 ) then
  634. Move( inp^, S^.buf[left], inlen );
  635. S^.buflen := left + inlen;
  636. Result:= 0;
  637. end;
  638. function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
  639. var
  640. i, left: csize_t;
  641. hash: array[0..Pred(BLAKE2B_PARALLELISM_DEGREE), 0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
  642. begin
  643. if (out_ = nil) or (outlen < S^.outlen) then Exit(-1);
  644. for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
  645. begin
  646. if ( S^.buflen > i * BLAKE2B_BLOCKBYTES ) then
  647. begin
  648. left := S^.buflen - i * BLAKE2B_BLOCKBYTES;
  649. if ( left > BLAKE2B_BLOCKBYTES ) then left := BLAKE2B_BLOCKBYTES;
  650. blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], left );
  651. end;
  652. blake2b_final( @S^.S[i], hash[i], BLAKE2B_OUTBYTES );
  653. end;
  654. for i := 0 to BLAKE2B_PARALLELISM_DEGREE -1 do
  655. blake2b_update( @S^.R, hash[i], BLAKE2B_OUTBYTES );
  656. Result:= blake2b_final( @S^.R, out_, S^.outlen );
  657. end;
  658. initialization
  659. {$IF DEFINED(CPUX86_64)}
  660. if AVXSupport then
  661. begin
  662. blake2s_compress:= @blake2s_compress_avx;
  663. blake2b_compress:= @blake2b_compress_avx;
  664. end
  665. else begin
  666. blake2s_compress:= @blake2s_compress_sse;
  667. blake2b_compress:= @blake2b_compress_sse;
  668. end;
  669. {$ELSE}
  670. blake2s_compress:= @blake2s_compress_pas;
  671. blake2b_compress:= @blake2b_compress_pas;
  672. {$ENDIF}
  673. end.