diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java index 8685f56ac77b995d3172f01c28e2701dc97ef6f2..be63cd61783c7ef10c255d0a887f4c305038936f 100644 --- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java +++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java @@ -336,7 +336,7 @@ class CryptoComponentImpl implements CryptoComponent { int macBytes = cipher.getMacBytes(); // The input contains the salt, iterations, IV, ciphertext and MAC if(input.length < PBKDF_SALT_BYTES + 4 + STORAGE_IV_BYTES + macBytes) - return null; // Invalid + return null; // Invalid input byte[] salt = new byte[PBKDF_SALT_BYTES]; System.arraycopy(input, 0, salt, 0, salt.length); long iterations = ByteUtils.readUint32(input, salt.length); @@ -366,28 +366,21 @@ class CryptoComponentImpl implements CryptoComponent { // Key derivation function based on a hash function - see NIST SP 800-56A, // section 5.8 - private byte[] concatenationKdf(byte[] rawSecret, byte[] label, - byte[] initiatorInfo, byte[] responderInfo) { + private byte[] concatenationKdf(byte[]... args) { // The output of the hash function must be long enough to use as a key MessageDigest messageDigest = getMessageDigest(); if(messageDigest.getDigestLength() < CIPHER_KEY_BYTES) throw new RuntimeException(); - // The length of every field must fit in an unsigned 8-bit integer - if(rawSecret.length > 255) throw new IllegalArgumentException(); - if(label.length > 255) throw new IllegalArgumentException(); - if(initiatorInfo.length > 255) throw new IllegalArgumentException(); - if(responderInfo.length > 255) throw new IllegalArgumentException(); - // All fields are length-prefixed - messageDigest.update((byte) rawSecret.length); - messageDigest.update(rawSecret); - messageDigest.update((byte) label.length); - messageDigest.update(label); - messageDigest.update((byte) initiatorInfo.length); - messageDigest.update(initiatorInfo); - messageDigest.update((byte) responderInfo.length); - messageDigest.update(responderInfo); + // Each argument is length-prefixed - the length must fit in an + // unsigned 8-bit integer + for(byte[] arg : args) { + if(arg.length > 255) throw new IllegalArgumentException(); + messageDigest.update((byte) arg.length); + messageDigest.update(arg); + } byte[] hash = messageDigest.digest(); - // The secret is the first CIPHER_KEY_BYTES bytes of the hash + // The output is the first CIPHER_KEY_BYTES bytes of the hash + if(hash.length == CIPHER_KEY_BYTES) return hash; byte[] output = new byte[CIPHER_KEY_BYTES]; System.arraycopy(hash, 0, output, 0, output.length); return output; @@ -410,7 +403,7 @@ class CryptoComponentImpl implements CryptoComponent { int macLength = prf.getMacSize(); // The output of the PRF must be long enough to use as a key if(macLength < CIPHER_KEY_BYTES) throw new RuntimeException(); - byte[] mac = new byte[macLength], output = new byte[CIPHER_KEY_BYTES]; + byte[] mac = new byte[macLength]; prf.update((byte) 0); // Counter prf.update(label, 0, label.length); // Null-terminated byte[] contextBytes = new byte[4]; @@ -418,6 +411,9 @@ class CryptoComponentImpl implements CryptoComponent { prf.update(contextBytes, 0, contextBytes.length); prf.update((byte) CIPHER_KEY_BYTES); // Output length prf.doFinal(mac, 0); + // The output is the first CIPHER_KEY_BYTES bytes of the MAC + if(mac.length == CIPHER_KEY_BYTES) return mac; + byte[] output = new byte[CIPHER_KEY_BYTES]; System.arraycopy(mac, 0, output, 0, output.length); return output; } diff --git a/briar-core/src/org/briarproject/crypto/CryptoModule.java b/briar-core/src/org/briarproject/crypto/CryptoModule.java index d4ac20c6495d50fd7c21f3c8a339a0579cb8ec9b..3cdaf74041683bae608eb3cfcdf890939daeeb4c 100644 --- a/briar-core/src/org/briarproject/crypto/CryptoModule.java +++ b/briar-core/src/org/briarproject/crypto/CryptoModule.java @@ -42,6 +42,7 @@ public class CryptoModule extends AbstractModule { @Override protected void configure() { + bind(AuthenticatedCipher.class).to(AuthenticatedCipherImpl.class); bind(CryptoComponent.class).to( CryptoComponentImpl.class).in(Singleton.class); bind(PasswordStrengthEstimator.class).to( diff --git a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java b/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java index 23ea5e245ccd6925d73414ac4644c0eee339310c..205fc2e5e2de488d71a40278173b9176d13d0da8 100644 --- a/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java +++ b/briar-core/src/org/briarproject/crypto/StreamDecrypterFactoryImpl.java @@ -3,6 +3,7 @@ package org.briarproject.crypto; import java.io.InputStream; import javax.inject.Inject; +import javax.inject.Provider; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.SecretKey; @@ -13,10 +14,13 @@ import org.briarproject.api.transport.StreamContext; class StreamDecrypterFactoryImpl implements StreamDecrypterFactory { private final CryptoComponent crypto; + private final Provider<AuthenticatedCipher> cipherProvider; @Inject - StreamDecrypterFactoryImpl(CryptoComponent crypto) { + StreamDecrypterFactoryImpl(CryptoComponent crypto, + Provider<AuthenticatedCipher> cipherProvider) { this.crypto = crypto; + this.cipherProvider = cipherProvider; } public StreamDecrypter createStreamDecrypter(InputStream in, @@ -27,7 +31,7 @@ class StreamDecrypterFactoryImpl implements StreamDecrypterFactory { boolean alice = !ctx.getAlice(); SecretKey frameKey = crypto.deriveFrameKey(secret, streamNumber, alice); // Create the decrypter - AuthenticatedCipher cipher = new AuthenticatedCipherImpl(); + AuthenticatedCipher cipher = cipherProvider.get(); return new StreamDecrypterImpl(in, cipher, frameKey); } @@ -36,7 +40,7 @@ class StreamDecrypterFactoryImpl implements StreamDecrypterFactory { // Derive the frame key SecretKey frameKey = crypto.deriveFrameKey(secret, 0, alice); // Create the decrypter - AuthenticatedCipher cipher = new AuthenticatedCipherImpl(); + AuthenticatedCipher cipher = cipherProvider.get(); return new StreamDecrypterImpl(in, cipher, frameKey); } } diff --git a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java b/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java index ae0429e05e952b8f60699767291f9e837e2e2841..90fd2af20e97deb33a7668f07e91c49be02ffcb7 100644 --- a/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java +++ b/briar-core/src/org/briarproject/crypto/StreamEncrypterFactoryImpl.java @@ -5,6 +5,7 @@ import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH; import java.io.OutputStream; import javax.inject.Inject; +import javax.inject.Provider; import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.SecretKey; @@ -15,10 +16,13 @@ import org.briarproject.api.transport.StreamContext; class StreamEncrypterFactoryImpl implements StreamEncrypterFactory { private final CryptoComponent crypto; + private final Provider<AuthenticatedCipher> cipherProvider; @Inject - StreamEncrypterFactoryImpl(CryptoComponent crypto) { + StreamEncrypterFactoryImpl(CryptoComponent crypto, + Provider<AuthenticatedCipher> cipherProvider) { this.crypto = crypto; + this.cipherProvider = cipherProvider; } public StreamEncrypter createStreamEncrypter(OutputStream out, @@ -33,7 +37,7 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory { // Derive the frame key SecretKey frameKey = crypto.deriveFrameKey(secret, streamNumber, alice); // Create the encrypter - AuthenticatedCipher cipher = new AuthenticatedCipherImpl(); + AuthenticatedCipher cipher = cipherProvider.get(); return new StreamEncrypterImpl(out, cipher, frameKey, tag); } @@ -42,7 +46,7 @@ class StreamEncrypterFactoryImpl implements StreamEncrypterFactory { // Derive the frame key SecretKey frameKey = crypto.deriveFrameKey(secret, 0, alice); // Create the encrypter - AuthenticatedCipher cipher = new AuthenticatedCipherImpl(); + AuthenticatedCipher cipher = cipherProvider.get(); return new StreamEncrypterImpl(out, cipher, frameKey, null); } }