diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/Id.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/Id.kt index 91a9238352..11c32853e7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/Id.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/Id.kt @@ -29,6 +29,21 @@ data class Id(val address: ByteArray) { return ByteBuffer.wrap(address).int.toLong() and 0xffffffffL } + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Id + + if (!address.contentEquals(other.address)) return false + + return true + } + + override fun hashCode(): Int { + return address.contentHashCode() + } + companion object { private const val PERIPHERAL_NODE_INDEX = 1 // TODO: understand the meaning of this value. It comes from preferences diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt index 23b7ae8054..48f07aa2ab 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecrypt.kt @@ -61,6 +61,6 @@ class EnDecrypt(private val aapsLogger: AAPSLogger, private val nonce: Nonce, pr companion object { - private val MAC_SIZE = 8 + private const val MAC_SIZE = 8 } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt index 893ba05655..7c52b2694e 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncoding.kt @@ -7,7 +7,7 @@ import java.nio.ByteBuffer /*** * String prefix and length encoding and decoding. Example message: */ -class StringLengthPrefixEncoding { +class StringLengthPrefixEncoding private constructor() { companion object { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt index 5f36fcf5c9..90130a29f0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchange.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair import com.google.crypto.tink.subtle.X25519 import info.nightscout.androidaps.logging.AAPSLogger -import info.nightscout.androidaps.logging.AAPSLoggerTest import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.MessageIOException @@ -12,10 +11,11 @@ import org.spongycastle.crypto.macs.CMac import org.spongycastle.crypto.params.KeyParameter import java.security.SecureRandom -class KeyExchange(private val aapsLogger: AAPSLogger, - var pdmPrivate: ByteArray = X25519.generatePrivateKey(), - val pdmNonce: ByteArray = ByteArray(NONCE_SIZE) - ) { +class KeyExchange( + private val aapsLogger: AAPSLogger, + var pdmPrivate: ByteArray = X25519.generatePrivateKey(), + val pdmNonce: ByteArray = ByteArray(NONCE_SIZE) +) { val pdmPublic = X25519.publicFromPrivate(pdmPrivate) var podPublic = ByteArray(PUBLIC_KEY_SIZE) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessage.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessage.kt index de5dd8c45d..e66684a770 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessage.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapMessage.kt @@ -23,7 +23,7 @@ enum class EapCode(val code: Byte) { data class EapMessage( val code: EapCode, val identifier: Byte, - val attributes: Array, + val attributes: Array ) { fun toByteArray(): ByteArray { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapSqn.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapSqn.kt deleted file mode 100644 index 03408f8735..0000000000 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/EapSqn.kt +++ /dev/null @@ -1,18 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session - -import java.nio.ByteBuffer - -/*** - * Eap-Aka start session sequence. - * Incremented for each new session - */ -class EapSqn(var sqn: Long) { - - fun increment(): ByteArray { - sqn++ - return ByteBuffer.allocate(8) - .putLong(sqn) - .array() - .copyOfRange(2, 8) - } -} diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt index da37dcfa71..41c7e9855b 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/session/SessionEstablisher.kt @@ -37,7 +37,7 @@ class SessionEstablisher( fun negotiateSessionKeys(): SessionKeys { // send EAP-AKA challenge - msgSeq++ // TODO: get from pod state. This only works for activating a new pod + msgSeq++ var challenge = eapAkaChallenge() msgIO.sendMessage(challenge) @@ -80,7 +80,7 @@ class SessionEstablisher( } private fun processChallengeResponse(challengeResponse: MessagePacket) { - // TODO verify that identifier matches identifer from the Challenge + // TODO verify that identifier matches identifier from the Challenge val eapMsg = EapMessage.parse(aapsLogger, challengeResponse.payload) if (eapMsg.attributes.size != 2) { aapsLogger.debug(LTag.PUMPBTCOMM, "EAP-AKA: got message: $eapMsg") diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt index a85f9c9c1c..7846261526 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/endecrypt/EnDecryptTest.kt @@ -11,23 +11,24 @@ class EnDecryptTest { @Test fun decrypt() { - // TODO: add data received from the pod - // this test is failing because the way we increment the nonce + val received = + "54,57,11,a1,0c,16,03,00,08,20,2e,a9,08,20,2e,a8,34,7c,b9,7b,38,5d,45,a3,c4,0e,40,4c,55,71,5e,f3,c3,86,50,17,36,7e,62,3c,7d,0b,46,9e,81,cd,fd,9a".replace( + ",", + "" + ) + val decryptedPayload = + "30,2e,30,3d,00,12,08,20,2e,a9,1c,0a,1d,05,00,16,b0,00,00,00,0b,ff,01,fe".replace(",", "") val aapsLogger = AAPSLoggerTest() val enDecrypt = EnDecrypt( aapsLogger, Nonce( - Hex.decode("dda23c090a0a0a0a"), - 0 + Hex.decode("6c,ff,5d,18,b7,61,6c,ae".replace(",", "")), + 22 ), - Hex.decode("ba1283744b6de9fab6d9b77d95a71d6e") + Hex.decode("55,79,9f,d2,66,64,cb,f6,e4,76,52,5e,2d,ee,52,c6".replace(",", "")) ) - val encryptedMessage = Hex.decode( - "54571101070003400242000002420001" + - "e09158bcb0285a81bf30635f3a17ee73f0afbb3286bc524a8a66" + - "fb1bc5b001e56543" - ) - val decrypted = Hex.decode("53302e303d000effffffff00060704ffffffff82b22c47302e30") + val encryptedMessage = Hex.decode(received) + val decrypted = Hex.decode(decryptedPayload) val msg = MessagePacket.parse(encryptedMessage) val decryptedMsg = enDecrypt.decrypt(msg) diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt new file mode 100644 index 0000000000..519f06fa9e --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/MessagePacketTest.kt @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message + +import com.google.crypto.tink.subtle.Hex +import info.nightscout.androidaps.logging.AAPSLoggerTest +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id +import info.nightscout.androidaps.utils.extensions.toHex +import org.junit.Assert.* +import org.junit.Test + +class MessagePacketTest { + + val payload = + "54,57,11,01,07,00,03,40,08,20,2e,a8,08,20,2e,a9,ab,35,d8,31,60,9b,b8,fe,3a,3b,de,5b,18,37,24,9a,16,db,f8,e4,d3,05,e9,75,dc,81,7c,37,07,cc,41,5f,af,8a".replace( + ",", + "" + ) + + @Test fun testParseMessagePacket() { + val aapsLogger = AAPSLoggerTest() + val msg = MessagePacket.parse(Hex.decode(payload)) + assertEquals(msg.type, MessageType.ENCRYPTED) + assertEquals(msg.source, Id.fromLong(136326824)) + assertEquals(msg.destination, Id.fromLong(136326825)) + assertEquals(msg.sequenceNumber, 7.toByte()) + assertEquals(msg.ackNumber, 0.toByte()) + assertEquals(msg.eqos, 1.toShort()) + assertEquals(msg.priority, false) + assertEquals(msg.lastMessage, false) + assertEquals(msg.gateway, false) + assertEquals(msg.sas, true) + assertEquals(msg.tfs, false) + assertEquals(msg.version, 0.toShort()) + assertEquals(msg.payload.toHex(), payload.substring(32, payload.length)) + } + + @Test fun testSerializeMessagePacket() { + val msg = MessagePacket( + type = MessageType.ENCRYPTED, + source = Id.fromLong(136326824), + destination = Id.fromLong(136326825), + sequenceNumber = 7.toByte(), + ackNumber = 0.toByte(), + eqos = 1.toShort(), + priority = false, + lastMessage = false, + gateway = false, + sas = true, + tfs = false, + payload = Hex.decode(payload.substring(32, payload.length)) + ) + assertEquals(msg.asByteArray().toHex(), payload) + } +} diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt new file mode 100644 index 0000000000..5ceed4dd49 --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadJoinerTest.kt @@ -0,0 +1,20 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message + +import com.google.crypto.tink.subtle.Hex +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.PayloadJoiner +import info.nightscout.androidaps.utils.extensions.toHex +import org.junit.Assert.assertEquals +import org.junit.Test + +class PayloadJoinerTest { + + @Test fun testJoiner() { + val f1 = Hex.decode("00,01,54,57,10,23,03,00,00,c0,ff,ff,ff,fe,08,20,2e,a8,50,30".replace(",", "")) + val f2 = Hex.decode("01,04,bc,20,1f,f6,3d,00,01,a5,ff,ff,ff,fe,08,20,2e,a8,50,30".replace(",", "")) + val payload = "54,57,10,23,03,00,00,c0,ff,ff,ff,fe,08,20,2e,a8,50,30,3d,00,01,a5".replace(",", "") + val joiner = PayloadJoiner(f1) + joiner.accumulate(f2) + val actual = joiner.finalize() + assertEquals(payload, actual.toHex()) + } +} diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt new file mode 100644 index 0000000000..6eecdf780f --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitJoinTest.kt @@ -0,0 +1,26 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.PayloadJoiner +import info.nightscout.androidaps.utils.extensions.toHex +import org.junit.Assert.assertEquals +import org.junit.Test +import java.util.* + +class PayloadSplitJoinTest { + private val random = Random(42) + + @Test fun testSplitAndJoinBack() { + for (s in 0..250) { + val payload = ByteArray(s) + random.nextBytes(payload) + val splitter = PayloadSplitter(payload) + val packets = splitter.splitInPackets() + val joiner = PayloadJoiner(packets.get(0).asByteArray()) + for (p in packets.subList(1, packets.size)) { + joiner.accumulate(p.asByteArray()) + } + val got = joiner.finalize() + assertEquals(got.toHex(), payload.toHex()) + } + } +} diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt new file mode 100644 index 0000000000..8d046c0439 --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/PayloadSplitterTest.kt @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message + +import com.google.crypto.tink.subtle.Hex +import info.nightscout.androidaps.utils.extensions.toHex +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class PayloadSplitterTest { + @Test fun testSplitter() { + val f1 = "00,01,54,57,10,23,03,00,00,c0,ff,ff,ff,fe,08,20,2e,a8,50,30".replace(",", "") + val f2 = "01,04,bc,20,1f,f6,3d,00,01,a5,ff,ff,ff,fe,08,20,2e,a8,50,30".replace(",", "") + val payload = Hex.decode("54,57,10,23,03,00,00,c0,ff,ff,ff,fe,08,20,2e,a8,50,30,3d,00,01,a5".replace(",", "")) + + val splitter = PayloadSplitter(payload) + val packets = splitter.splitInPackets() + + assertEquals(packets.size, 2) + assertEquals(f1, packets.get(0).asByteArray().toHex()) + val p2 = packets.get(1).asByteArray() + assertTrue(p2.size >= 10) + assertEquals(f2.subSequence(0, 20), p2.copyOfRange(0, 10).toHex()) + } +} diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt new file mode 100644 index 0000000000..96bce14845 --- /dev/null +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/message/StringLengthPrefixEncodingTest.kt @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message + +import com.google.crypto.tink.subtle.Hex +import info.nightscout.androidaps.utils.extensions.toHex +import org.junit.Assert.* +import org.junit.Test + +class StringLengthPrefixEncodingTest { + private val p0Payload = Hex.decode("50,30,3d,00,01,a5".replace(",", "")) // from logs + private val p0Content = Hex.decode("a5") + + @Test fun testFormatKeysP0() { + val payload = StringLengthPrefixEncoding.formatKeys(arrayOf("P0="), arrayOf(p0Content)) + assertEquals(p0Payload.toHex(), payload.toHex()) + } + + @Test fun testParseKeysP0() { + val parsed = StringLengthPrefixEncoding.parseKeys(arrayOf("P0="), p0Payload) + assertEquals(parsed.size, 1) + assertEquals(parsed[0].toHex(), p0Content.toHex()) + } +} diff --git a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt index 7d8fcf7edf..51d4bca126 100644 --- a/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt +++ b/omnipod-dash/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/pair/KeyExchangeTest.kt @@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair import info.nightscout.androidaps.logging.AAPSLoggerTest import info.nightscout.androidaps.utils.extensions.toHex -import org.junit.Assert import org.junit.Assert.* import org.junit.Test import org.spongycastle.util.encoders.Hex @@ -12,15 +11,15 @@ class KeyExchangeTest { val aapsLogger = AAPSLoggerTest() val ke = KeyExchange( aapsLogger, - pdmPrivate= Hex.decode("27ec94b71a201c5e92698d668806ae5ba00594c307cf5566e60c1fc53a6f6bb6"), - pdmNonce= Hex.decode("edfdacb242c7f4e1d2bc4d93ca3c5706") + pdmPrivate = Hex.decode("27ec94b71a201c5e92698d668806ae5ba00594c307cf5566e60c1fc53a6f6bb6"), + pdmNonce = Hex.decode("edfdacb242c7f4e1d2bc4d93ca3c5706") ) val podPublicKey = Hex.decode("2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74") val podNonce = Hex.decode("00000000000000000000000000000000") - ke.updatePodPublicData(podPublicKey+podNonce) + ke.updatePodPublicData(podPublicKey + podNonce) assertEquals(ke.pdmPublic.toHex(), "f2b6940243aba536a66e19fb9a39e37f1e76a1cd50ab59b3e05313b4fc93975e") assertEquals(ke.pdmConf.toHex(), "5fc3b4da865e838ceaf1e9e8bb85d1ac") ke.validatePodConf(Hex.decode("af4f10db5f96e5d9cd6cfc1f54f4a92f")) assertEquals(ke.ltk.toHex(), "341e16d13f1cbf73b19d1c2964fee02b") } -} \ No newline at end of file +}