Added SMS transport support for PreKeyBundle messages.

1) Added SMS transport support.

2) Keep track of whether a PreKeyBundle message has gotten
   a response, and send them as subsequent messages until
   one has been received.
This commit is contained in:
Moxie Marlinspike
2013-08-21 19:34:11 -07:00
parent c3b8b62d32
commit 1bbcedabd4
14 changed files with 221 additions and 42 deletions

View File

@@ -107,6 +107,11 @@ public class KeyUtil {
(SessionRecord.hasSession(context, recipient));
}
public static boolean isNonPrekeySessionFor(Context context, MasterSecret masterSecret, CanonicalRecipientAddress recipient) {
return isSessionFor(context, recipient) &&
!(new SessionRecord(context, masterSecret, recipient).isPrekeyBundleRequired());
}
public static boolean isIdentityKeyFor(Context context,
MasterSecret masterSecret,
CanonicalRecipientAddress recipient)

View File

@@ -36,17 +36,17 @@ public class MessageCipher {
public static final int SUPPORTED_VERSION = 2;
public static final int CRADLE_AGREEMENT_VERSION = 2;
static final int VERSION_LENGTH = 1;
public static final int VERSION_LENGTH = 1;
private static final int SENDER_KEY_ID_LENGTH = 3;
private static final int RECEIVER_KEY_ID_LENGTH = 3;
static final int NEXT_KEY_LENGTH = PublicKey.KEY_SIZE;
public static final int NEXT_KEY_LENGTH = PublicKey.KEY_SIZE;
private static final int COUNTER_LENGTH = 3;
public static final int HEADER_LENGTH = VERSION_LENGTH + SENDER_KEY_ID_LENGTH + RECEIVER_KEY_ID_LENGTH + COUNTER_LENGTH + NEXT_KEY_LENGTH;
static final int VERSION_OFFSET = 0;
public static final int VERSION_OFFSET = 0;
private static final int SENDER_KEY_ID_OFFSET = VERSION_OFFSET + VERSION_LENGTH;
static final int RECEIVER_KEY_ID_OFFSET = SENDER_KEY_ID_OFFSET + SENDER_KEY_ID_LENGTH;
static final int NEXT_KEY_OFFSET = RECEIVER_KEY_ID_OFFSET + RECEIVER_KEY_ID_LENGTH;
public static final int RECEIVER_KEY_ID_OFFSET = SENDER_KEY_ID_OFFSET + SENDER_KEY_ID_LENGTH;
public static final int NEXT_KEY_OFFSET = RECEIVER_KEY_ID_OFFSET + RECEIVER_KEY_ID_LENGTH;
private static final int COUNTER_OFFSET = NEXT_KEY_OFFSET + NEXT_KEY_LENGTH;
private static final int TEXT_OFFSET = COUNTER_OFFSET + COUNTER_LENGTH;

View File

@@ -131,6 +131,7 @@ public class SessionCipher {
context.getSessionRecord().setSessionKey(context.getSessionKey());
context.getSessionRecord().setSessionVersion(context.getNegotiatedVersion());
context.getSessionRecord().setPrekeyBundleRequired(false);
context.getSessionRecord().save();
return plaintextWithPadding;

View File

@@ -0,0 +1,44 @@
/**
* Copyright (C) 2013 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.push;
import org.whispersystems.textsecure.crypto.TransportDetails;
import org.whispersystems.textsecure.util.Base64;
import java.io.IOException;
public class PushTransportDetails implements TransportDetails {
@Override
public byte[] getStrippedPaddingMessageBody(byte[] messageWithPadding) {
return messageWithPadding;
}
@Override
public byte[] getPaddedMessageBody(byte[] messageBody) {
return messageBody;
}
@Override
public byte[] getEncodedMessage(byte[] messageWithMac) {
return Base64.encodeBytesWithoutPadding(messageWithMac).getBytes();
}
@Override
public byte[] getDecodedMessage(byte[] encodedMessageBytes) throws IOException {
return Base64.decodeWithoutPadding(new String(encodedMessageBytes));
}
}

View File

@@ -36,8 +36,9 @@ import java.nio.channels.FileChannel;
*/
public class SessionRecord extends Record {
private static final int CURRENT_VERSION_MARKER = 0X55555556;
private static final int[] VALID_VERSION_MARKERS = {CURRENT_VERSION_MARKER, 0X55555555};
private static final int CURRENT_VERSION_MARKER = 0X55555557;
private static final int[] VALID_VERSION_MARKERS = {CURRENT_VERSION_MARKER, 0X55555556, 0X55555555};
private static final Object FILE_LOCK = new Object();
private int counter;
@@ -48,6 +49,7 @@ public class SessionRecord extends Record {
private IdentityKey identityKey;
private SessionKey sessionKeyRecord;
private boolean verifiedSessionKey;
private boolean prekeyBundleRequired;
private final MasterSecret masterSecret;
@@ -63,7 +65,7 @@ public class SessionRecord extends Record {
}
public static void delete(Context context, CanonicalRecipientAddress recipient) {
delete(context, SESSIONS_DIRECTORY, getRecipientId(context, recipient)+"");
delete(context, SESSIONS_DIRECTORY, getRecipientId(context, recipient) + "");
}
public static boolean hasSession(Context context, CanonicalRecipientAddress recipient) {
@@ -116,6 +118,14 @@ public class SessionRecord extends Record {
return this.identityKey;
}
public boolean isPrekeyBundleRequired() {
return prekeyBundleRequired;
}
public void setPrekeyBundleRequired(boolean prekeyBundleRequired) {
this.prekeyBundleRequired = prekeyBundleRequired;
}
// public void setVerifiedSessionKey(boolean verifiedSessionKey) {
// this.verifiedSessionKey = verifiedSessionKey;
// }
@@ -162,6 +172,7 @@ public class SessionRecord extends Record {
writeInteger(sessionVersion, out);
writeIdentityKey(out);
writeInteger(verifiedSessionKey ? 1 : 0, out);
writeInteger(prekeyBundleRequired ? 1 : 0, out);
if (sessionKeyRecord != null)
writeBlob(sessionKeyRecord.serialize(), out);
@@ -202,6 +213,10 @@ public class SessionRecord extends Record {
this.verifiedSessionKey = (readInteger(in) == 1);
}
if (versionMarker >= 0X55555557) {
this.prekeyBundleRequired = (readInteger(in) == 1);
}
if (in.available() != 0)
this.sessionKeyRecord = new SessionKey(readBlob(in), masterSecret);
@@ -226,4 +241,5 @@ public class SessionRecord extends Record {
return null;
}
}