Better FS Locking.

pull/1/head
Moxie Marlinspike 10 years ago
parent c8757c2134
commit 79020cd33c

@ -1,3 +1,13 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
}
}
apply plugin: 'android-library' apply plugin: 'android-library'
repositories { repositories {

@ -25,16 +25,17 @@ public class PreKeyEntity implements PreKey {
@Expose(serialize = false) @Expose(serialize = false)
private int deviceId; private int deviceId;
@Expose(serialize = false)
private int registrationId;
private int keyId; private int keyId;
private ECPublicKey publicKey; private ECPublicKey publicKey;
private IdentityKey identityKey; private IdentityKey identityKey;
private int registrationId;
public PreKeyEntity(int keyId, ECPublicKey publicKey, IdentityKey identityKey) { public PreKeyEntity(int keyId, ECPublicKey publicKey, IdentityKey identityKey) {
this.keyId = keyId; this.keyId = keyId;
this.publicKey = publicKey; this.publicKey = publicKey;
this.identityKey = identityKey; this.identityKey = identityKey;
this.registrationId = registrationId;
} }
public int getDeviceId() { public int getDeviceId() {

@ -22,6 +22,7 @@ public class TextSecurePreKeyStore implements PreKeyStore {
public static final String PREKEY_DIRECTORY = "prekeys"; public static final String PREKEY_DIRECTORY = "prekeys";
private static final int CURRENT_VERSION_MARKER = 1; private static final int CURRENT_VERSION_MARKER = 1;
private static final Object FILE_LOCK = new Object();
private static final String TAG = TextSecurePreKeyStore.class.getSimpleName(); private static final String TAG = TextSecurePreKeyStore.class.getSimpleName();
private final Context context; private final Context context;
@ -34,39 +35,43 @@ public class TextSecurePreKeyStore implements PreKeyStore {
@Override @Override
public PreKeyRecord load(int preKeyId) throws InvalidKeyIdException { public PreKeyRecord load(int preKeyId) throws InvalidKeyIdException {
try { synchronized (FILE_LOCK) {
MasterCipher masterCipher = new MasterCipher(masterSecret); try {
FileInputStream fin = new FileInputStream(getPreKeyFile(preKeyId)); MasterCipher masterCipher = new MasterCipher(masterSecret);
int recordVersion = readInteger(fin); FileInputStream fin = new FileInputStream(getPreKeyFile(preKeyId));
int recordVersion = readInteger(fin);
if (recordVersion != CURRENT_VERSION_MARKER) {
throw new AssertionError("Invalid version: " + recordVersion); if (recordVersion != CURRENT_VERSION_MARKER) {
throw new AssertionError("Invalid version: " + recordVersion);
}
byte[] serializedRecord = masterCipher.decryptBytes(readBlob(fin));
return new PreKeyRecord(serializedRecord);
} catch (IOException | InvalidMessageException e) {
Log.w(TAG, e);
throw new InvalidKeyIdException(e);
} }
byte[] serializedRecord = masterCipher.decryptBytes(readBlob(fin));
return new PreKeyRecord(serializedRecord);
} catch (IOException | InvalidMessageException e) {
Log.w(TAG, e);
throw new InvalidKeyIdException(e);
} }
} }
@Override @Override
public void store(int preKeyId, PreKeyRecord record) { public void store(int preKeyId, PreKeyRecord record) {
try { synchronized (FILE_LOCK) {
MasterCipher masterCipher = new MasterCipher(masterSecret); try {
RandomAccessFile recordFile = new RandomAccessFile(getPreKeyFile(preKeyId), "rw"); MasterCipher masterCipher = new MasterCipher(masterSecret);
FileChannel out = recordFile.getChannel(); RandomAccessFile recordFile = new RandomAccessFile(getPreKeyFile(preKeyId), "rw");
FileChannel out = recordFile.getChannel();
out.position(0);
writeInteger(CURRENT_VERSION_MARKER, out); out.position(0);
writeBlob(masterCipher.encryptBytes(record.serialize()), out); writeInteger(CURRENT_VERSION_MARKER, out);
out.truncate(out.position()); writeBlob(masterCipher.encryptBytes(record.serialize()), out);
out.truncate(out.position());
recordFile.close();
} catch (IOException e) { recordFile.close();
throw new AssertionError(e); } catch (IOException e) {
throw new AssertionError(e);
}
} }
} }

@ -74,19 +74,21 @@ public class TextSecureSessionStore implements SessionStore {
@Override @Override
public void store(long recipientId, int deviceId, SessionRecord record) { public void store(long recipientId, int deviceId, SessionRecord record) {
try { synchronized (FILE_LOCK) {
MasterCipher masterCipher = new MasterCipher(masterSecret); try {
RandomAccessFile sessionFile = new RandomAccessFile(getSessionFile(recipientId, deviceId), "rw"); MasterCipher masterCipher = new MasterCipher(masterSecret);
FileChannel out = sessionFile.getChannel(); RandomAccessFile sessionFile = new RandomAccessFile(getSessionFile(recipientId, deviceId), "rw");
FileChannel out = sessionFile.getChannel();
out.position(0);
writeInteger(CURRENT_VERSION, out); out.position(0);
writeBlob(masterCipher.encryptBytes(record.serialize()), out); writeInteger(CURRENT_VERSION, out);
out.truncate(out.position()); writeBlob(masterCipher.encryptBytes(record.serialize()), out);
out.truncate(out.position());
sessionFile.close();
} catch (IOException e) { sessionFile.close();
throw new AssertionError(e); } catch (IOException e) {
throw new AssertionError(e);
}
} }
} }

Loading…
Cancel
Save