Skip to content
Snippets Groups Projects
Commit 41d3c604 authored by Volker Richert's avatar Volker Richert
Browse files

Merge remote-tracking branch 'remotes/upstream/master'

parents 286e99d2 a323eb70
No related branches found
No related tags found
No related merge requests found
Showing with 129 additions and 20 deletions
......@@ -340,7 +340,6 @@ public class GetHmacAndKeyActivity extends AppCompatActivity implements LoaderCa
String key = MessageUtils.byteArrayToHexString((byte[]) keyResponse.readObject());
realm.beginTransaction();
info.setHmac(hmac);
info.setKey(key);
realm.commitTransaction();
}
......
......@@ -9,6 +9,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
......@@ -36,6 +37,7 @@ import info.nightscout.android.medtronic.message.PumpStatusResponseMessage;
import info.nightscout.android.medtronic.message.PumpTimeRequestMessage;
import info.nightscout.android.medtronic.message.PumpTimeResponseMessage;
import info.nightscout.android.medtronic.message.ReadInfoResponseMessage;
import info.nightscout.android.medtronic.message.RequestLinkKeyResponseMessage;
import info.nightscout.android.medtronic.message.UnexpectedMessageException;
import info.nightscout.android.model.medtronicNg.PumpStatusEvent;
import info.nightscout.android.utils.HexDump;
......@@ -238,7 +240,7 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
Log.d(TAG, "Finished enterPasshtroughMode");
}
public void openConnection() throws IOException, TimeoutException {
public void openConnection() throws IOException, TimeoutException, NoSuchAlgorithmException {
Log.d(TAG, "Begin openConnection");
new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.OPEN_CONNECTION, mPumpSession, mPumpSession.getHMAC()).send(this);
// FIXME - We need to care what the response message is - wrong MAC and all that
......@@ -264,6 +266,24 @@ public class MedtronicCnlReader implements ContourNextLinkMessageHandler {
Log.d(TAG, String.format("Finished requestReadInfo. linkMAC = '%d', pumpMAC = '%d", linkMAC, pumpMAC));
}
public void requestLinkKey() throws IOException, TimeoutException, EncryptionException, ChecksumException {
Log.d(TAG, "Begin requestLinkKey");
new ContourNextLinkBinaryMessage(ContourNextLinkBinaryMessage.CommandType.REQUEST_LINK_KEY, mPumpSession, null).send(this);
ContourNextLinkMessage response = RequestLinkKeyResponseMessage.fromBytes(mPumpSession, readMessage());
// FIXME - this needs to go into RequestLinkKeyResponseMessage
ByteBuffer infoBuffer = ByteBuffer.allocate(55);
infoBuffer.order(ByteOrder.BIG_ENDIAN);
infoBuffer.put(response.encode(), 0x21, 55);
byte[] packedLinkKey = infoBuffer.array();
this.getPumpSession().setPackedLinkKey(packedLinkKey);
Log.d(TAG, String.format("Finished requestLinkKey. linkKey = '%s'", this.getPumpSession().getKey()));
}
public byte negotiateChannel(byte lastRadioChannel) throws IOException, ChecksumException, TimeoutException {
ArrayList<Byte> radioChannels = new ArrayList<>(Arrays.asList(ArrayUtils.toObject(RADIO_CHANNELS)));
......
package info.nightscout.android.medtronic;
import org.apache.commons.lang3.ArrayUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Created by lgoedhart on 26/03/2016.
*/
public class MedtronicCnlSession {
private static final String HMAC_PADDING = "A4BD6CED9A42602564F413123";
private byte[] HMAC;
private byte[] key;
private String stickSerial;
private long linkMAC;
private long pumpMAC;
......@@ -14,16 +23,31 @@ public class MedtronicCnlSession {
private int bayerSequenceNumber = 1;
private int medtronicSequenceNumber = 1;
public byte[] getHMAC() {
/*public byte[] getHMAC() {
return HMAC;
}*/
public byte[] getHMAC() throws NoSuchAlgorithmException {
String shortSerial = this.stickSerial.replaceAll("\\d+-", "");
byte[] message = (shortSerial + HMAC_PADDING).getBytes();
byte[] numArray;
MessageDigest instance = MessageDigest.getInstance("SHA-256");
instance.update(message);
numArray = instance.digest();
ArrayUtils.reverse(numArray);
return numArray;
}
public byte[] getKey() {
return key;
}
public byte[] getIV() {
byte[] iv = new byte[key.length];
System.arraycopy(key,0,iv,0,key.length);
System.arraycopy(key, 0, iv, 0, key.length);
iv[0] = radioChannel;
return iv;
}
......@@ -32,7 +56,7 @@ public class MedtronicCnlSession {
return linkMAC;
}
public void setLinkMAC( long linkMAC ) {
public void setLinkMAC(long linkMAC) {
this.linkMAC = linkMAC;
}
......@@ -40,7 +64,7 @@ public class MedtronicCnlSession {
return pumpMAC;
}
public void setPumpMAC( long pumpMAC ) {
public void setPumpMAC(long pumpMAC) {
this.pumpMAC = pumpMAC;
}
......@@ -68,11 +92,39 @@ public class MedtronicCnlSession {
this.radioChannel = radioChannel;
}
public void setHMAC( byte[] hmac ) {
public void setHMAC(byte[] hmac) {
this.HMAC = hmac;
}
public void setKey( byte[] key ) {
public void setKey(byte[] key) {
this.key = key;
}
public void setPackedLinkKey(byte[] packedLinkKey) {
this.key = new byte[16];
int pos = this.stickSerial.charAt(this.stickSerial.length() - 1) & 7;
for (int i = 0; i < this.key.length; i++) {
if ((packedLinkKey[pos + 1] & 1) == 1) {
this.key[i] = (byte) ~packedLinkKey[pos];
} else {
this.key[i] = packedLinkKey[pos];
}
if (((packedLinkKey[pos + 1] >> 1) & 1) == 0) {
pos += 3;
} else {
pos += 2;
}
}
}
public String getStickSerial() {
return stickSerial;
}
public void setStickSerial(String stickSerial) {
this.stickSerial = stickSerial;
}
}
......@@ -34,6 +34,10 @@ public class ContourNextLinkBinaryMessage extends ContourNextLinkMessage{
CommandType(int commandType) {
value = (byte) commandType;
}
public int getValue() {
return value;
}
}
public ContourNextLinkBinaryMessage(CommandType commandType, MedtronicCnlSession pumpSession, byte[] payload) {
......
......@@ -45,7 +45,10 @@ public class MedtronicReceiveMessage extends MedtronicMessage {
// TODO - Validate the message, inner CCITT, serial numbers, etc
// If there's not 57 bytes, then we got back a bad message. Not sure how to process these yet.
if( bytes.length >= 57 ) {
// Also, READ_INFO and REQUEST_LINK_KEY are not encrypted
if (bytes.length >= 57 &&
(bytes[18] != CommandType.READ_INFO.getValue()) &&
(bytes[18] != CommandType.REQUEST_LINK_KEY_RESPONSE.getValue())) {
// Replace the encrypted bytes by their decrypted equivalent (same block size)
byte encryptedPayloadSize = bytes[56];
......
package info.nightscout.android.medtronic.message;
import info.nightscout.android.medtronic.MedtronicCnlSession;
/**
* Created by lgoedhart on 10/05/2016.
*/
public class RequestLinkKeyResponseMessage extends MedtronicReceiveMessage {
protected RequestLinkKeyResponseMessage(CommandType commandType, CommandAction commandAction, MedtronicCnlSession pumpSession, byte[] payload) {
super(commandType, commandAction, pumpSession, payload);
}
public static ContourNextLinkMessage fromBytes(MedtronicCnlSession pumpSession, byte[] bytes) throws ChecksumException, EncryptionException {
// TODO - turn this into a factory
ContourNextLinkMessage message = MedtronicReceiveMessage.fromBytes(pumpSession, bytes);
// TODO - Validate the MessageType
return message;
}
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeoutException;
......@@ -157,6 +158,9 @@ public class MedtronicCnlIntentService extends IntentService {
info = realm.copyToRealm(info);
}
cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
/*
String hmac = info.getHmac();
String key = info.getKey();
......@@ -173,6 +177,7 @@ public class MedtronicCnlIntentService extends IntentService {
cnlReader.getPumpSession().setHMAC(MessageUtils.hexStringToByteArray(hmac));
cnlReader.getPumpSession().setKey(MessageUtils.hexStringToByteArray(key));
*/
cnlReader.enterControlMode();
......@@ -181,6 +186,17 @@ public class MedtronicCnlIntentService extends IntentService {
cnlReader.openConnection();
cnlReader.requestReadInfo();
String key = info.getKey();
if (key == null) {
cnlReader.requestLinkKey();
info.setKey(MessageUtils.byteArrayToHexString(cnlReader.getPumpSession().getKey()));
key = info.getKey();
}
cnlReader.getPumpSession().setKey(MessageUtils.hexStringToByteArray(key));
long pumpMAC = cnlReader.getPumpSession().getPumpMAC();
Log.i(TAG, "PumpInfo MAC: " + (pumpMAC & 0xffffff));
MainActivity.setActivePumpMac(pumpMAC);
......@@ -250,6 +266,9 @@ public class MedtronicCnlIntentService extends IntentService {
} catch (UnexpectedMessageException e) {
Log.e(TAG, "Unexpected Message", e);
sendStatus("Communication Error: " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Could not determine CNL HMAC", e);
sendStatus("Error connecting to Contour Next Link: Hashing error.");
} finally {
//TODO : 05.11.2016 has the close to be here?
cnlReader.closeConnection();
......@@ -304,7 +323,7 @@ public class MedtronicCnlIntentService extends IntentService {
final Intent receiverIntent = new Intent(this, XDripPlusUploadReceiver.class);
final long timestamp = System.currentTimeMillis() + 500L;
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int) timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT);
Log.d(TAG,"Scheduling xDrip+ send");
Log.d(TAG, "Scheduling xDrip+ send");
wakeUpIntent(getApplicationContext(), timestamp, pendingIntent);
}
}
......@@ -312,7 +331,7 @@ public class MedtronicCnlIntentService extends IntentService {
private void uploadToNightscout() {
Intent receiverIntent = new Intent(this, NightscoutUploadReceiver.class);
final long timestamp = System.currentTimeMillis() + 1000L;
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int)timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, (int) timestamp, receiverIntent, PendingIntent.FLAG_ONE_SHOT);
wakeUpIntent(getApplicationContext(), timestamp, pendingIntent);
}
......
......@@ -9,7 +9,6 @@ import io.realm.annotations.PrimaryKey;
public class ContourNextLinkInfo extends RealmObject {
@PrimaryKey
private String serialNumber;
private String hmac;
private String key;
public String getSerialNumber() {
......@@ -20,14 +19,6 @@ public class ContourNextLinkInfo extends RealmObject {
this.serialNumber = serialNumber;
}
public String getHmac() {
return hmac;
}
public void setHmac(String hmac) {
this.hmac = hmac;
}
public String getKey() {
return key;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment