33import org .bouncycastle .crypto .Digest ;
44import org .bouncycastle .crypto .digests .Blake2bDigest ;
55import org .bouncycastle .crypto .params .Argon2Parameters ;
6+ import org .bouncycastle .crypto .params .Argon2Parameters .BlockPool ;
7+ import org .bouncycastle .crypto .params .Argon2Parameters .FixedBlockPool ;
68import org .bouncycastle .util .Arrays ;
79import org .bouncycastle .util .Longs ;
810import org .bouncycastle .util .Pack ;
@@ -37,6 +39,8 @@ public class Argon2BytesGenerator
3739 private static final byte [] ZERO_BYTES = new byte [4 ];
3840
3941 private Argon2Parameters parameters ;
42+ private BlockPool pool ;
43+ private int memoryBlocks ;
4044 private Block [] memory ;
4145 private int segmentLength ;
4246 private int laneLength ;
@@ -98,6 +102,7 @@ public int generateBytes(byte[] password, byte[] out, int outOff, int outLen)
98102
99103 byte [] tmpBlockBytes = new byte [ARGON2_BLOCK_SIZE ];
100104
105+ initMemory (memoryBlocks );
101106 initialize (tmpBlockBytes , password , outLen );
102107 fillMemoryBlocks ();
103108 digest (tmpBlockBytes , out , outOff , outLen );
@@ -118,17 +123,18 @@ private void reset()
118123 Block b = memory [i ];
119124 if (null != b )
120125 {
121- b . clear ( );
126+ pool . deallocate ( b );
122127 }
123128 }
124129 }
130+ memory = null ;
125131 }
126132
127133 private void doInit (Argon2Parameters parameters )
128134 {
129135 /* 2. Align memory size */
130136 /* Minimum memoryBlocks = 8L blocks, where L is the number of lanes */
131- int memoryBlocks = parameters .getMemory ();
137+ memoryBlocks = parameters .getMemory ();
132138
133139 if (memoryBlocks < 2 * Argon2BytesGenerator .ARGON2_SYNC_POINTS * parameters .getLanes ())
134140 {
@@ -141,7 +147,11 @@ private void doInit(Argon2Parameters parameters)
141147 /* Ensure that all segments have equal length */
142148 memoryBlocks = segmentLength * (parameters .getLanes () * Argon2BytesGenerator .ARGON2_SYNC_POINTS );
143149
144- initMemory (memoryBlocks );
150+ pool = parameters .getBlockPool ();
151+ if (pool == null ) {
152+ // if no pool is provided hold on to enough blocks for the primary memory
153+ pool = new FixedBlockPool (memoryBlocks );
154+ }
145155 }
146156
147157 private void initMemory (int memoryBlocks )
@@ -150,13 +160,13 @@ private void initMemory(int memoryBlocks)
150160
151161 for (int i = 0 ; i < memory .length ; i ++)
152162 {
153- memory [i ] = new Block ();
163+ memory [i ] = pool . allocate ();
154164 }
155165 }
156166
157167 private void fillMemoryBlocks ()
158168 {
159- FillBlock filler = new FillBlock ();
169+ FillBlock filler = new FillBlock (pool );
160170 Position position = new Position ();
161171 for (int pass = 0 ; pass < parameters .getIterations (); ++pass )
162172 {
@@ -174,6 +184,7 @@ private void fillMemoryBlocks()
174184 }
175185 }
176186 }
187+ filler .deallocate (pool );
177188 }
178189
179190 private void fillSegment (FillBlock filler , Position position )
@@ -548,16 +559,31 @@ private void fillFirstBlocks(byte[] tmpBlockBytes, byte[] initialHashWithZeros)
548559
549560 private long intToLong (int x )
550561 {
551- return ( long )( x & M32L ) ;
562+ return x & M32L ;
552563 }
553564
554565 private static class FillBlock
555566 {
556- Block R = new Block ();
557- Block Z = new Block ();
567+ final Block R ;
568+ final Block Z ;
569+
570+ final Block addressBlock ;
571+ final Block inputBlock ;
558572
559- Block addressBlock = new Block ();
560- Block inputBlock = new Block ();
573+ private FillBlock (BlockPool pool ) {
574+ R = pool .allocate ();
575+ Z = pool .allocate ();
576+
577+ addressBlock = pool .allocate ();
578+ inputBlock = pool .allocate ();
579+ }
580+
581+ public void deallocate (BlockPool pool ) {
582+ pool .deallocate (addressBlock );
583+ pool .deallocate (inputBlock );
584+ pool .deallocate (R );
585+ pool .deallocate (Z );
586+ }
561587
562588 private void applyBlake ()
563589 {
@@ -618,14 +644,14 @@ private void fillBlockWithXor(Block X, Block Y, Block currentBlock)
618644 }
619645 }
620646
621- private static class Block
647+ public static class Block
622648 {
623649 private static final int SIZE = ARGON2_QWORDS_IN_BLOCK ;
624650
625651 /* 128 * 8 Byte QWords */
626652 private final long [] v ;
627653
628- private Block ()
654+ public Block ()
629655 {
630656 v = new long [SIZE ];
631657 }
0 commit comments