diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java index 7d3e4b70b2..5b0b362187 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionBuilder.java @@ -116,7 +116,7 @@ public class SessionBuilder { return; } - boolean simultaneousInitiate = sessionRecord.getSessionState().hasPendingPreKey(); + boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); AxolotlParameters.Builder parameters = AxolotlParameters.newBuilder(); @@ -166,7 +166,7 @@ public class SessionBuilder { } SessionRecord sessionRecord = sessionStore.loadSession(recipientId, deviceId); - boolean simultaneousInitiate = sessionRecord.getSessionState().hasPendingPreKey(); + boolean simultaneousInitiate = sessionRecord.getSessionState().hasUnacknowledgedPreKeyMessage(); AxolotlParameters.Builder parameters = RatchetingSession.AxolotlParameters.newBuilder(); parameters.setTheirBaseKey(message.getBaseKey()); @@ -247,7 +247,7 @@ public class SessionBuilder { preKey.getSignedPreKey() == null ? 2 : 3, parameters.create()); - sessionRecord.getSessionState().setPendingPreKey(preKey.getPreKeyId(), preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey()); + sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(preKey.getPreKeyId(), preKey.getSignedPreKeyId(), ourBaseKey.getPublicKey()); sessionRecord.getSessionState().setLocalRegistrationId(identityKeyStore.getLocalRegistrationId()); sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId()); @@ -389,10 +389,8 @@ public class SessionBuilder { sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ephemeralKey, identityKey); sessionStore.storeSession(recipientId, deviceId, sessionRecord); - return new KeyExchangeMessage(2, sequence, flags, - baseKey.getPublicKey(), null, - ephemeralKey.getPublicKey(), - identityKey.getPublicKey(), null); + return new KeyExchangeMessage(2, sequence, flags, baseKey.getPublicKey(), null, + ephemeralKey.getPublicKey(), identityKey.getPublicKey(), null); } diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java index 59c60c9ab6..faaf87d710 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/SessionCipher.java @@ -43,6 +43,8 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import static org.whispersystems.libaxolotl.state.SessionState.UnacknowledgedPreKeyMessageItems; + /** * The main entry point for Axolotl encrypt/decrypt operations. * @@ -96,15 +98,12 @@ public class SessionCipher { senderEphemeral, chainKey.getIndex(), previousCounter, ciphertextBody); - if (sessionState.hasPendingPreKey()) { - int pendingPreKeyId = sessionState.getPendingPreKeyId(); - int pendingSignedPreKeyId = sessionState.getPendingSignedPreKeyId(); - ECPublicKey pendingBaseKey = sessionState.getPendingBaseKey(); - int localRegistrationId = sessionState.getLocalRegistrationId(); + if (sessionState.hasUnacknowledgedPreKeyMessage()) { + UnacknowledgedPreKeyMessageItems items = sessionState.getUnacknowledgedPreKeyMessageItems(); + int localRegistrationId = sessionState.getLocalRegistrationId(); - ciphertextMessage = new PreKeyWhisperMessage(sessionVersion, - localRegistrationId, pendingPreKeyId, - pendingSignedPreKeyId, pendingBaseKey, + ciphertextMessage = new PreKeyWhisperMessage(sessionVersion, localRegistrationId, items.getPreKeyId(), + items.getSignedPreKeyId(), items.getBaseKey(), sessionState.getLocalIdentityKey(), sessionState.getVerification(), (WhisperMessage) ciphertextMessage); @@ -185,7 +184,7 @@ public class SessionCipher { byte[] plaintext = getPlaintext(messageKeys, ciphertextMessage.getBody()); - sessionState.clearPendingPreKey(); + sessionState.clearUnacknowledgedPreKeyMessage(); return plaintext; diff --git a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java index 40bf50a919..29cb027699 100644 --- a/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java +++ b/libaxolotl/src/main/java/org/whispersystems/libaxolotl/state/SessionState.java @@ -423,7 +423,7 @@ public class SessionState { return sessionStructure.hasPendingKeyExchange(); } - public void setPendingPreKey(int preKeyId, int signedPreKeyId, ECPublicKey baseKey) { + public void setUnacknowledgedPreKeyMessage(int preKeyId, int signedPreKeyId, ECPublicKey baseKey) { PendingPreKey pending = PendingPreKey.newBuilder() .setPreKeyId(preKeyId) .setSignedPreKeyId(signedPreKeyId) @@ -435,27 +435,24 @@ public class SessionState { .build(); } - public boolean hasPendingPreKey() { + public boolean hasUnacknowledgedPreKeyMessage() { return this.sessionStructure.hasPendingPreKey(); } - public int getPendingPreKeyId() { - return sessionStructure.getPendingPreKey().getPreKeyId(); - } - - public int getPendingSignedPreKeyId() { - return sessionStructure.getPendingPreKey().getSignedPreKeyId(); - } - - public ECPublicKey getPendingBaseKey() { + public UnacknowledgedPreKeyMessageItems getUnacknowledgedPreKeyMessageItems() { try { - return Curve.decodePoint(sessionStructure.getPendingPreKey().getBaseKey().toByteArray(), 0); + return + new UnacknowledgedPreKeyMessageItems(sessionStructure.getPendingPreKey().getPreKeyId(), + sessionStructure.getPendingPreKey().getSignedPreKeyId(), + Curve.decodePoint(sessionStructure.getPendingPreKey() + .getBaseKey() + .toByteArray(), 0)); } catch (InvalidKeyException e) { throw new AssertionError(e); } } - public void clearPendingPreKey() { + public void clearUnacknowledgedPreKeyMessage() { this.sessionStructure = this.sessionStructure.toBuilder() .clearPendingPreKey() .build(); @@ -484,4 +481,29 @@ public class SessionState { public byte[] serialize() { return sessionStructure.toByteArray(); } + + public static class UnacknowledgedPreKeyMessageItems { + private final int preKeyId; + private final int signedPreKeyId; + private final ECPublicKey baseKey; + + public UnacknowledgedPreKeyMessageItems(int preKeyId, int signedPreKeyId, ECPublicKey baseKey) { + this.preKeyId = preKeyId; + this.signedPreKeyId = signedPreKeyId; + this.baseKey = baseKey; + } + + + public int getPreKeyId() { + return preKeyId; + } + + public int getSignedPreKeyId() { + return signedPreKeyId; + } + + public ECPublicKey getBaseKey() { + return baseKey; + } + } } diff --git a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java index 680c455a5b..8128465513 100644 --- a/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java +++ b/src/org/thoughtcrime/securesms/crypto/KeyExchangeInitiator.java @@ -83,6 +83,6 @@ public class KeyExchangeInitiator { SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); SessionRecord sessionRecord = sessionStore.loadSession(recipient.getRecipientId(), RecipientDevice.DEFAULT_DEVICE_ID); - return sessionRecord.getSessionState().hasPendingPreKey(); + return sessionRecord.getSessionState().hasPendingKeyExchange(); } }