commit
2892d385ab
|
@ -0,0 +1,128 @@
|
||||||
|
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
|
||||||
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
|
import org.spongycastle.crypto.engines.AESEngine
|
||||||
|
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)
|
||||||
|
) {
|
||||||
|
val pdmPublic = X25519.publicFromPrivate(pdmPrivate)
|
||||||
|
|
||||||
|
var podPublic = ByteArray(PUBLIC_KEY_SIZE)
|
||||||
|
var podNonce = ByteArray(NONCE_SIZE)
|
||||||
|
|
||||||
|
val podConf = ByteArray(CMAC_SIZE)
|
||||||
|
val pdmConf = ByteArray(CMAC_SIZE)
|
||||||
|
|
||||||
|
var ltk = ByteArray(CMAC_SIZE)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (pdmNonce.all { it == 0.toByte() }) {
|
||||||
|
// pdmNonce is in the constructor for tests
|
||||||
|
val random = SecureRandom()
|
||||||
|
random.nextBytes(pdmNonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePodPublicData(payload: ByteArray) {
|
||||||
|
if (payload.size != PUBLIC_KEY_SIZE + NONCE_SIZE) {
|
||||||
|
throw MessageIOException("Invalid payload size")
|
||||||
|
}
|
||||||
|
podPublic = payload.copyOfRange(0, PUBLIC_KEY_SIZE)
|
||||||
|
podNonce = payload.copyOfRange(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE + NONCE_SIZE)
|
||||||
|
generateKeys()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun validatePodConf(payload: ByteArray) {
|
||||||
|
if (!podConf.contentEquals(payload)) {
|
||||||
|
aapsLogger.warn(
|
||||||
|
LTag.PUMPBTCOMM,
|
||||||
|
"Received invalid podConf. Expected: ${podConf.toHex()}. Got: ${payload.toHex()}"
|
||||||
|
)
|
||||||
|
throw MessageIOException("Invalid podConf value received")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateKeys() {
|
||||||
|
val curveLTK = X25519.computeSharedSecret(pdmPrivate, podPublic)
|
||||||
|
|
||||||
|
val firstKey = podPublic.copyOfRange(podPublic.size - 4, podPublic.size) +
|
||||||
|
pdmPublic.copyOfRange(pdmPublic.size - 4, pdmPublic.size) +
|
||||||
|
podNonce.copyOfRange(podNonce.size - 4, podNonce.size) +
|
||||||
|
pdmNonce.copyOfRange(pdmNonce.size - 4, pdmNonce.size)
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "First key for LTK: ${firstKey.toHex()}")
|
||||||
|
|
||||||
|
val intermediateKey = ByteArray(CMAC_SIZE)
|
||||||
|
aesCmac(firstKey, curveLTK, intermediateKey)
|
||||||
|
|
||||||
|
val ltkData = byteArrayOf(2.toByte()) +
|
||||||
|
INTERMEDIARY_KEY_MAGIC_STRING +
|
||||||
|
podNonce +
|
||||||
|
pdmNonce +
|
||||||
|
byteArrayOf(0.toByte(), 1.toByte())
|
||||||
|
aesCmac(intermediateKey, ltkData, ltk)
|
||||||
|
|
||||||
|
val confData = byteArrayOf(1.toByte()) +
|
||||||
|
INTERMEDIARY_KEY_MAGIC_STRING +
|
||||||
|
podNonce +
|
||||||
|
pdmNonce +
|
||||||
|
byteArrayOf(0.toByte(), 1.toByte())
|
||||||
|
val confKey = ByteArray(CMAC_SIZE)
|
||||||
|
aesCmac(intermediateKey, confData, confKey)
|
||||||
|
|
||||||
|
val pdmConfData = PDM_CONF_MAGIC_PREFIX +
|
||||||
|
pdmNonce +
|
||||||
|
podNonce
|
||||||
|
aesCmac(confKey, pdmConfData, pdmConf)
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmConf: ${pdmConf.toHex()}")
|
||||||
|
|
||||||
|
val podConfData = POD_CONF_MAGIC_PREFIX +
|
||||||
|
podNonce +
|
||||||
|
pdmNonce
|
||||||
|
aesCmac(confKey, podConfData, podConf)
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "podConf: ${podConf.toHex()}")
|
||||||
|
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmPrivate: ${pdmPrivate.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmPublic: ${pdmPublic.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "podPublic: ${podPublic.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmNonce: ${pdmNonce.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "podNonce: ${podNonce.toHex()}")
|
||||||
|
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "LTK, donna key: ${curveLTK.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Intermediate key: ${intermediateKey.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "LTK: ${ltk.toHex()}")
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Conf KEY: ${confKey.toHex()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private const val PUBLIC_KEY_SIZE = 32
|
||||||
|
private const val NONCE_SIZE = 16
|
||||||
|
|
||||||
|
const val CMAC_SIZE = 16
|
||||||
|
|
||||||
|
private val INTERMEDIARY_KEY_MAGIC_STRING = "TWIt".toByteArray()
|
||||||
|
private val PDM_CONF_MAGIC_PREFIX = "KC_2_U".toByteArray()
|
||||||
|
private val POD_CONF_MAGIC_PREFIX = "KC_2_V".toByteArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun aesCmac(key: ByteArray, data: ByteArray, result: ByteArray) {
|
||||||
|
val aesEngine = AESEngine()
|
||||||
|
val mac = CMac(aesEngine)
|
||||||
|
mac.init(KeyParameter(key))
|
||||||
|
mac.update(data, 0, data.size)
|
||||||
|
mac.doFinal(result, 0)
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair
|
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.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
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.Id
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.MessageIOException
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO
|
||||||
|
@ -12,27 +10,17 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding.Companion.parseKeys
|
||||||
import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
|
import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
|
||||||
import info.nightscout.androidaps.utils.extensions.toHex
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
import org.spongycastle.crypto.engines.AESEngine
|
|
||||||
import org.spongycastle.crypto.macs.CMac
|
|
||||||
import org.spongycastle.crypto.params.KeyParameter
|
|
||||||
import java.security.SecureRandom
|
|
||||||
|
|
||||||
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO, val myId: Id, val podId: Id, val podAddress: Id) {
|
internal class LTKExchanger(
|
||||||
|
private val aapsLogger: AAPSLogger,
|
||||||
|
private val msgIO: MessageIO,
|
||||||
|
val myId: Id,
|
||||||
|
val podId: Id,
|
||||||
|
val podAddress: Id
|
||||||
|
) {
|
||||||
|
|
||||||
private val pdmPrivate = X25519.generatePrivateKey()
|
private val keyExchange = KeyExchange(aapsLogger)
|
||||||
private val pdmPublic = X25519.publicFromPrivate(pdmPrivate)
|
|
||||||
private var podPublic = ByteArray(PUBLIC_KEY_SIZE)
|
|
||||||
private var podNonce = ByteArray(NONCE_SIZE)
|
|
||||||
private val pdmNonce = ByteArray(NONCE_SIZE)
|
|
||||||
private val pdmConf = ByteArray(CMAC_SIZE)
|
|
||||||
private val podConf = ByteArray(CMAC_SIZE)
|
|
||||||
private var seq: Byte = 1
|
private var seq: Byte = 1
|
||||||
private var ltk = ByteArray(CMAC_SIZE)
|
|
||||||
|
|
||||||
init {
|
|
||||||
val random = SecureRandom()
|
|
||||||
random.nextBytes(pdmNonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun negotiateLTK(): PairResult {
|
fun negotiateLTK(): PairResult {
|
||||||
// send SP1, SP2
|
// send SP1, SP2
|
||||||
|
@ -48,7 +36,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
val podSps1 = msgIO.receiveMessage()
|
val podSps1 = msgIO.receiveMessage()
|
||||||
processSps1FromPod(podSps1)
|
processSps1FromPod(podSps1)
|
||||||
// now we have all the data to generate: confPod, confPdm, ltk and noncePrefix
|
// now we have all the data to generate: confPod, confPdm, ltk and noncePrefix
|
||||||
generateKeys()
|
|
||||||
seq++
|
seq++
|
||||||
// send SPS2
|
// send SPS2
|
||||||
val sps2 = sps2()
|
val sps2 = sps2()
|
||||||
|
@ -66,13 +54,13 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
// TODO: failing to read or validate p0 will lead to undefined state
|
// TODO: failing to read or validate p0 will lead to undefined state
|
||||||
// It could be that:
|
// It could be that:
|
||||||
// - the pod answered with p0 and we did not receive/could not process the answer
|
// - the pod answered with p0 and we did not receive/could not process the answer
|
||||||
// - the pod answered with some sort of error
|
// - the pod answered with some sort of error. This is very unlikely, because we already received(and validated) SPS2 from the pod
|
||||||
// But if sps2 conf value is incorrect, then we would probablysee this when receiving the pod podSps2(to test)
|
// But if sps2 conf value is incorrect, then we would probablysee this when receiving the pod podSps2(to test)
|
||||||
val p0 = msgIO.receiveMessage()
|
val p0 = msgIO.receiveMessage()
|
||||||
validateP0(p0)
|
validateP0(p0)
|
||||||
|
|
||||||
return PairResult(
|
return PairResult(
|
||||||
ltk = ltk,
|
ltk = keyExchange.ltk,
|
||||||
msgSeq = seq
|
msgSeq = seq
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -93,7 +81,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
private fun sps1(): PairMessage {
|
private fun sps1(): PairMessage {
|
||||||
val payload = StringLengthPrefixEncoding.formatKeys(
|
val payload = StringLengthPrefixEncoding.formatKeys(
|
||||||
arrayOf("SPS1="),
|
arrayOf("SPS1="),
|
||||||
arrayOf(pdmPublic + pdmNonce)
|
arrayOf(keyExchange.pdmPublic + keyExchange.pdmNonce)
|
||||||
)
|
)
|
||||||
return PairMessage(
|
return PairMessage(
|
||||||
sequenceNumber = seq,
|
sequenceNumber = seq,
|
||||||
|
@ -107,17 +95,13 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS1 from pod: ${msg.payload.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS1 from pod: ${msg.payload.toHex()}")
|
||||||
|
|
||||||
val payload = parseKeys(arrayOf(SPS1), msg.payload)[0]
|
val payload = parseKeys(arrayOf(SPS1), msg.payload)[0]
|
||||||
if (payload.size != 48) {
|
keyExchange.updatePodPublicData(payload)
|
||||||
throw MessageIOException("Invalid payload size")
|
|
||||||
}
|
|
||||||
podPublic = payload.copyOfRange(0, PUBLIC_KEY_SIZE)
|
|
||||||
podNonce = payload.copyOfRange(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE + NONCE_SIZE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sps2(): PairMessage {
|
private fun sps2(): PairMessage {
|
||||||
val payload = StringLengthPrefixEncoding.formatKeys(
|
val payload = StringLengthPrefixEncoding.formatKeys(
|
||||||
arrayOf(SPS2),
|
arrayOf(SPS2),
|
||||||
arrayOf(pdmConf)
|
arrayOf(keyExchange.pdmConf)
|
||||||
)
|
)
|
||||||
return PairMessage(
|
return PairMessage(
|
||||||
sequenceNumber = seq,
|
sequenceNumber = seq,
|
||||||
|
@ -133,16 +117,10 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
val payload = parseKeys(arrayOf(SPS2), msg.payload)[0]
|
val payload = parseKeys(arrayOf(SPS2), msg.payload)[0]
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "SPS2 payload from pod: ${payload.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "SPS2 payload from pod: ${payload.toHex()}")
|
||||||
|
|
||||||
if (payload.size != CMAC_SIZE) {
|
if (payload.size != KeyExchange.CMAC_SIZE) {
|
||||||
throw MessageIOException("Invalid payload size")
|
throw MessageIOException("Invalid payload size")
|
||||||
}
|
}
|
||||||
if (!podConf.contentEquals(payload)) {
|
keyExchange.validatePodConf(payload)
|
||||||
aapsLogger.warn(
|
|
||||||
LTag.PUMPBTCOMM,
|
|
||||||
"Received invalid podConf. Expected: ${podConf.toHex()}. Got: ${payload.toHex()}"
|
|
||||||
)
|
|
||||||
throw MessageIOException("Invalid podConf value received")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sp2(): ByteArray {
|
private fun sp2(): ByteArray {
|
||||||
|
@ -171,74 +149,10 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateKeys() {
|
|
||||||
val curveLTK = X25519.computeSharedSecret(pdmPrivate, podPublic)
|
|
||||||
|
|
||||||
val firstKey = podPublic.copyOfRange(podPublic.size - 4, podPublic.size) +
|
|
||||||
pdmPublic.copyOfRange(pdmPublic.size - 4, pdmPublic.size) +
|
|
||||||
podNonce.copyOfRange(podNonce.size - 4, podNonce.size) +
|
|
||||||
pdmNonce.copyOfRange(pdmNonce.size - 4, pdmNonce.size)
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "First key for LTK: ${firstKey.toHex()}")
|
|
||||||
|
|
||||||
val intermediateKey = ByteArray(CMAC_SIZE)
|
|
||||||
aesCmac(firstKey, curveLTK, intermediateKey)
|
|
||||||
|
|
||||||
val ltkData = byteArrayOf(2.toByte()) +
|
|
||||||
INTERMEDIAR_KEY_MAGIC_STRING +
|
|
||||||
podNonce +
|
|
||||||
pdmNonce +
|
|
||||||
byteArrayOf(0.toByte(), 1.toByte())
|
|
||||||
aesCmac(intermediateKey, ltkData, ltk)
|
|
||||||
|
|
||||||
val confData = byteArrayOf(1.toByte()) +
|
|
||||||
INTERMEDIAR_KEY_MAGIC_STRING +
|
|
||||||
podNonce +
|
|
||||||
pdmNonce +
|
|
||||||
byteArrayOf(0.toByte(), 1.toByte())
|
|
||||||
val confKey = ByteArray(CMAC_SIZE)
|
|
||||||
aesCmac(intermediateKey, confData, confKey)
|
|
||||||
|
|
||||||
val pdmConfData = PDM_CONF_MAGIC_PREFIX +
|
|
||||||
pdmNonce +
|
|
||||||
podNonce
|
|
||||||
aesCmac(confKey, pdmConfData, pdmConf)
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmConf: ${pdmConf.toHex()}")
|
|
||||||
|
|
||||||
val podConfData = POD_CONF_MAGIC_PREFIX +
|
|
||||||
podNonce +
|
|
||||||
pdmNonce
|
|
||||||
aesCmac(confKey, podConfData, podConf)
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "podConf: ${podConf.toHex()}")
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmPrivate: ${pdmPrivate.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmPublic: ${pdmPublic.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "podPublic: ${podPublic.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "pdmNonce: ${pdmNonce.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "podNonce: ${podNonce.toHex()}")
|
|
||||||
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "LTK, donna key: ${curveLTK.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Intermediate key: ${intermediateKey.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "LTK: ${ltk.toHex()}")
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Conf KEY: ${confKey.toHex()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val PUBLIC_KEY_SIZE = 32
|
private const val GET_POD_STATUS_HEX_COMMAND =
|
||||||
private const val NONCE_SIZE = 16
|
"ffc32dbd08030e0100008a" // TODO for now we are assuming this command is build out of constant parameters, use a proper command builder for that.
|
||||||
private const val CONF_SIZE = 16
|
|
||||||
|
|
||||||
private const val CMAC_SIZE = 16
|
|
||||||
|
|
||||||
private val INTERMEDIAR_KEY_MAGIC_STRING = "TWIt".toByteArray()
|
|
||||||
private val PDM_CONF_MAGIC_PREFIX = "KC_2_U".toByteArray()
|
|
||||||
private val POD_CONF_MAGIC_PREFIX = "KC_2_V".toByteArray()
|
|
||||||
|
|
||||||
private const val GET_POD_STATUS_HEX_COMMAND = "ffc32dbd08030e0100008a"
|
|
||||||
// TODO for now we are assuming this command is build out of constant parameters,
|
|
||||||
// use a proper command builder for that.
|
|
||||||
|
|
||||||
private const val SP1 = "SP1="
|
private const val SP1 = "SP1="
|
||||||
private const val SP2 = ",SP2="
|
private const val SP2 = ",SP2="
|
||||||
|
@ -249,11 +163,3 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
||||||
private val UNKNOWN_P0_PAYLOAD = byteArrayOf(0xa5.toByte())
|
private val UNKNOWN_P0_PAYLOAD = byteArrayOf(0xa5.toByte())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun aesCmac(key: ByteArray, data: ByteArray, result: ByteArray) {
|
|
||||||
val aesEngine = AESEngine()
|
|
||||||
val mac = CMac(aesEngine)
|
|
||||||
mac.init(KeyParameter(key))
|
|
||||||
mac.update(data, 0, data.size)
|
|
||||||
mac.doFinal(result, 0)
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ import java.security.SecureRandom
|
||||||
class SessionEstablisher(
|
class SessionEstablisher(
|
||||||
private val aapsLogger: AAPSLogger,
|
private val aapsLogger: AAPSLogger,
|
||||||
private val msgIO: MessageIO,
|
private val msgIO: MessageIO,
|
||||||
private val ltk: ByteArray,
|
ltk: ByteArray,
|
||||||
private val eapSqn: ByteArray,
|
eapSqn: ByteArray,
|
||||||
private val myId: Id,
|
private val myId: Id,
|
||||||
private val podId: Id,
|
private val podId: Id,
|
||||||
private var msgSeq: Byte
|
private var msgSeq: Byte
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
class KeyExchangeTest {
|
||||||
|
@Test fun testLTK() {
|
||||||
|
val aapsLogger = AAPSLoggerTest()
|
||||||
|
val ke = KeyExchange(
|
||||||
|
aapsLogger,
|
||||||
|
pdmPrivate= Hex.decode("27ec94b71a201c5e92698d668806ae5ba00594c307cf5566e60c1fc53a6f6bb6"),
|
||||||
|
pdmNonce= Hex.decode("edfdacb242c7f4e1d2bc4d93ca3c5706")
|
||||||
|
)
|
||||||
|
val podPublicKey = Hex.decode("2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74")
|
||||||
|
val podNonce = Hex.decode("00000000000000000000000000000000")
|
||||||
|
ke.updatePodPublicData(podPublicKey+podNonce)
|
||||||
|
assertEquals(ke.pdmPublic.toHex(), "f2b6940243aba536a66e19fb9a39e37f1e76a1cd50ab59b3e05313b4fc93975e")
|
||||||
|
assertEquals(ke.pdmConf.toHex(), "5fc3b4da865e838ceaf1e9e8bb85d1ac")
|
||||||
|
ke.validatePodConf(Hex.decode("af4f10db5f96e5d9cd6cfc1f54f4a92f"))
|
||||||
|
assertEquals(ke.ltk.toHex(), "341e16d13f1cbf73b19d1c2964fee02b")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue