Merge branch 'AbrahamKiggundu/briar-master': better lock encapsulation

This commit is contained in:
akwizgran
2015-01-29 11:27:30 +00:00
23 changed files with 944 additions and 517 deletions

View File

@@ -1,5 +1,8 @@
package org.briarproject.crypto;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.briarproject.api.crypto.MessageDigest;
import org.spongycastle.crypto.BlockCipher;
import org.spongycastle.crypto.digests.SHA256Digest;
@@ -16,7 +19,9 @@ class FortunaGenerator {
private static final int KEY_BYTES = 32;
private static final int BLOCK_BYTES = 16;
// All of the following are locking: this
private final Lock synchLock = new ReentrantLock();
// The following are locking: synchLock
private final MessageDigest digest = new DoubleDigest(new SHA256Digest());
private final BlockCipher cipher = new AESLightEngine();
private final byte[] key = new byte[KEY_BYTES];
@@ -28,56 +33,78 @@ class FortunaGenerator {
reseed(seed);
}
synchronized void reseed(byte[] seed) {
digest.update(key);
digest.update(seed);
digest.digest(key, 0, KEY_BYTES);
incrementCounter();
void reseed(byte[] seed) {
synchLock.lock();
try {
digest.update(key);
digest.update(seed);
digest.digest(key, 0, KEY_BYTES);
incrementCounter();
} finally {
synchLock.unlock();
}
}
// Package access for testing
synchronized void incrementCounter() {
counter[0]++;
for(int i = 0; counter[i] == 0; i++) {
if(i + 1 == BLOCK_BYTES)
throw new RuntimeException("Counter exhausted");
counter[i + 1]++;
void incrementCounter() {
synchLock.lock();
try {
counter[0]++;
for(int i = 0; counter[i] == 0; i++) {
if(i + 1 == BLOCK_BYTES)
throw new RuntimeException("Counter exhausted");
counter[i + 1]++;
}
} finally {
synchLock.unlock();
}
}
// Package access for testing
synchronized byte[] getCounter() {
return counter;
byte[] getCounter() {
synchLock.lock();
try {
return counter;
} finally {
synchLock.unlock();
}
}
synchronized int nextBytes(byte[] dest, int off, int len) {
// Don't write more than the maximum number of bytes in one request
if(len > MAX_BYTES_PER_REQUEST) len = MAX_BYTES_PER_REQUEST;
cipher.init(true, new KeyParameter(key));
// Generate full blocks directly into the output buffer
int fullBlocks = len / BLOCK_BYTES;
for(int i = 0; i < fullBlocks; i++) {
cipher.processBlock(counter, 0, dest, off + i * BLOCK_BYTES);
incrementCounter();
int nextBytes(byte[] dest, int off, int len) {
synchLock.lock();
try {
// Don't write more than the maximum number of bytes in one request
if(len > MAX_BYTES_PER_REQUEST) len = MAX_BYTES_PER_REQUEST;
cipher.init(true, new KeyParameter(key));
// Generate full blocks directly into the output buffer
int fullBlocks = len / BLOCK_BYTES;
for(int i = 0; i < fullBlocks; i++) {
cipher.processBlock(counter, 0, dest, off + i * BLOCK_BYTES);
incrementCounter();
}
// Generate a partial block if needed
int done = fullBlocks * BLOCK_BYTES, remaining = len - done;
assert remaining < BLOCK_BYTES;
if(remaining > 0) {
cipher.processBlock(counter, 0, buffer, 0);
incrementCounter();
// Copy the partial block to the output buffer and erase our copy
System.arraycopy(buffer, 0, dest, off + done, remaining);
for(int i = 0; i < BLOCK_BYTES; i++) buffer[i] = 0;
}
// Generate a new key
for(int i = 0; i < KEY_BYTES / BLOCK_BYTES; i++) {
cipher.processBlock(counter, 0, newKey, i * BLOCK_BYTES);
incrementCounter();
}
System.arraycopy(newKey, 0, key, 0, KEY_BYTES);
for(int i = 0; i < KEY_BYTES; i++) newKey[i] = 0;
// Return the number of bytes written
return len;
} finally {
synchLock.unlock();
}
// Generate a partial block if needed
int done = fullBlocks * BLOCK_BYTES, remaining = len - done;
assert remaining < BLOCK_BYTES;
if(remaining > 0) {
cipher.processBlock(counter, 0, buffer, 0);
incrementCounter();
// Copy the partial block to the output buffer and erase our copy
System.arraycopy(buffer, 0, dest, off + done, remaining);
for(int i = 0; i < BLOCK_BYTES; i++) buffer[i] = 0;
}
// Generate a new key
for(int i = 0; i < KEY_BYTES / BLOCK_BYTES; i++) {
cipher.processBlock(counter, 0, newKey, i * BLOCK_BYTES);
incrementCounter();
}
System.arraycopy(newKey, 0, key, 0, KEY_BYTES);
for(int i = 0; i < KEY_BYTES; i++) newKey[i] = 0;
// Return the number of bytes written
return len;
}
}

View File

@@ -14,7 +14,7 @@ class PseudoRandomImpl implements PseudoRandom {
generator = new FortunaGenerator(seed);
}
public synchronized byte[] nextBytes(int length) {
public byte[] nextBytes(int length) {
byte[] b = new byte[length];
int offset = 0;
while(offset < length) offset += generator.nextBytes(b, offset, length);