Skip to content

Commit

Permalink
fix: allows developers to provide a block pool to argon2
Browse files Browse the repository at this point in the history
closes: bcgit#1646

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
  • Loading branch information
shawkins committed May 2, 2024
1 parent d7ffa8b commit 5b1f02e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.params.Argon2Parameters;
import org.bouncycastle.crypto.params.Argon2Parameters.BlockPool;
import org.bouncycastle.crypto.params.Argon2Parameters.FixedBlockPool;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.Longs;
import org.bouncycastle.util.Pack;
Expand Down Expand Up @@ -37,6 +39,8 @@ public class Argon2BytesGenerator
private static final byte[] ZERO_BYTES = new byte[4];

private Argon2Parameters parameters;
private BlockPool pool;
private int memoryBlocks;
private Block[] memory;
private int segmentLength;
private int laneLength;
Expand Down Expand Up @@ -98,6 +102,7 @@ public int generateBytes(byte[] password, byte[] out, int outOff, int outLen)

byte[] tmpBlockBytes = new byte[ARGON2_BLOCK_SIZE];

initMemory(memoryBlocks);
initialize(tmpBlockBytes, password, outLen);
fillMemoryBlocks();
digest(tmpBlockBytes, out, outOff, outLen);
Expand All @@ -118,17 +123,18 @@ private void reset()
Block b = memory[i];
if (null != b)
{
b.clear();
pool.deallocate(b);
}
}
}
memory = null;
}

private void doInit(Argon2Parameters parameters)
{
/* 2. Align memory size */
/* Minimum memoryBlocks = 8L blocks, where L is the number of lanes */
int memoryBlocks = parameters.getMemory();
memoryBlocks = parameters.getMemory();

if (memoryBlocks < 2 * Argon2BytesGenerator.ARGON2_SYNC_POINTS * parameters.getLanes())
{
Expand All @@ -141,7 +147,11 @@ private void doInit(Argon2Parameters parameters)
/* Ensure that all segments have equal length */
memoryBlocks = segmentLength * (parameters.getLanes() * Argon2BytesGenerator.ARGON2_SYNC_POINTS);

initMemory(memoryBlocks);
pool = parameters.getBlockPool();
if (pool == null) {
// if no pool is provided hold on to enough blocks for the primary memory
pool = new FixedBlockPool(memoryBlocks);
}
}

private void initMemory(int memoryBlocks)
Expand All @@ -150,13 +160,13 @@ private void initMemory(int memoryBlocks)

for (int i = 0; i < memory.length; i++)
{
memory[i] = new Block();
memory[i] = pool.allocate();
}
}

private void fillMemoryBlocks()
{
FillBlock filler = new FillBlock();
FillBlock filler = new FillBlock(pool);
Position position = new Position();
for (int pass = 0; pass < parameters.getIterations(); ++pass)
{
Expand All @@ -174,6 +184,7 @@ private void fillMemoryBlocks()
}
}
}
filler.deallocate(pool);
}

private void fillSegment(FillBlock filler, Position position)
Expand Down Expand Up @@ -548,16 +559,31 @@ private void fillFirstBlocks(byte[] tmpBlockBytes, byte[] initialHashWithZeros)

private long intToLong(int x)
{
return (long)(x & M32L);
return x & M32L;
}

private static class FillBlock
{
Block R = new Block();
Block Z = new Block();
final Block R;
final Block Z;

final Block addressBlock;
final Block inputBlock;

Block addressBlock = new Block();
Block inputBlock = new Block();
private FillBlock(BlockPool pool) {
R = pool.allocate();
Z = pool.allocate();

addressBlock = pool.allocate();
inputBlock = pool.allocate();
}

public void deallocate(BlockPool pool) {
pool.deallocate(addressBlock);
pool.deallocate(inputBlock);
pool.deallocate(R);
pool.deallocate(Z);
}

private void applyBlake()
{
Expand Down Expand Up @@ -618,14 +644,14 @@ private void fillBlockWithXor(Block X, Block Y, Block currentBlock)
}
}

private static class Block
public static class Block
{
private static final int SIZE = ARGON2_QWORDS_IN_BLOCK;

/* 128 * 8 Byte QWords */
private final long[] v;

private Block()
public Block()
{
v = new long[SIZE];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,46 @@

import org.bouncycastle.crypto.CharToByteConverter;
import org.bouncycastle.crypto.PasswordConverter;
import org.bouncycastle.crypto.generators.Argon2BytesGenerator.Block;
import org.bouncycastle.util.Arrays;

import java.util.concurrent.LinkedBlockingQueue;

public class Argon2Parameters
{
public static interface BlockPool {
Block allocate();
void deallocate(Block block);
}

public static class FixedBlockPool implements BlockPool {

private LinkedBlockingQueue<Block> blocks;

public FixedBlockPool(int maxBlocks) {
this.blocks = new LinkedBlockingQueue<>(maxBlocks);
}

@Override
public Block allocate() {
Block block = blocks.poll();
if (block == null) {
return new Block();
}
// since we're not tracking which thread deallocated
// we don't know if the clearing is visible in this one
block.clear();
return block;
}

@Override
public void deallocate(Block block) {
block.clear();
blocks.offer(block);
}

}

public static final int ARGON2_d = 0x00;
public static final int ARGON2_i = 0x01;
public static final int ARGON2_id = 0x02;
Expand All @@ -31,9 +67,11 @@ public static class Builder

private int version;
private final int type;

private CharToByteConverter converter = PasswordConverter.UTF8;

private BlockPool blockPool;

public Builder()
{
this(DEFAULT_TYPE);
Expand Down Expand Up @@ -97,16 +135,22 @@ public Builder withVersion(int version)
this.version = version;
return this;
}

public Builder withCharToByteConverter(CharToByteConverter converter)
{
this.converter = converter;
return this;
}

public Builder withBlockPool(BlockPool blockPool)
{
this.blockPool = blockPool;
return this;
}

public Argon2Parameters build()
{
return new Argon2Parameters(type, salt, secret, additional, iterations, memory, lanes, version, converter);
return new Argon2Parameters(type, salt, secret, additional, iterations, memory, lanes, version, converter, blockPool);
}

public void clear()
Expand All @@ -129,6 +173,8 @@ public void clear()
private final int type;
private final CharToByteConverter converter;

private final BlockPool blockPool;

private Argon2Parameters(
int type,
byte[] salt,
Expand All @@ -138,7 +184,8 @@ private Argon2Parameters(
int memory,
int lanes,
int version,
CharToByteConverter converter)
CharToByteConverter converter,
BlockPool blockPool)
{

this.salt = Arrays.clone(salt);
Expand All @@ -150,6 +197,7 @@ private Argon2Parameters(
this.version = version;
this.type = type;
this.converter = converter;
this.blockPool = blockPool;
}

public byte[] getSalt()
Expand Down Expand Up @@ -197,6 +245,10 @@ public CharToByteConverter getCharToByteConverter()
return converter;
}

public BlockPool getBlockPool() {
return blockPool;
}

public void clear()
{
Arrays.clear(salt);
Expand Down

0 comments on commit 5b1f02e

Please sign in to comment.