dash ble tlk: start generating keys

This commit is contained in:
Andrei Vereha 2021-02-27 18:33:04 +01:00
parent 39408ac535
commit ddfbd2e7bd

View file

@ -1,21 +1,32 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk
import com.google.crypto.tink.mac.AesCmacKeyManager
import com.google.crypto.tink.proto.AesCmac
import com.google.crypto.tink.subtle.X25519 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.driver.comm.Id import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
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
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding
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 java.security.SecureRandom import java.security.SecureRandom
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) { internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) {
private val privateKey = X25519.generatePrivateKey() private val pdmPrivate = X25519.generatePrivateKey()
private val nonce = ByteArray(16) 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 confPdm = ByteArray(CONF_SIZE)
private val confPod = ByteArray(CONF_SIZE)
private val controllerId = Id.fromInt(OmnipodDashBleManagerImpl.CONTROLLER_ID) private val controllerId = Id.fromInt(OmnipodDashBleManagerImpl.CONTROLLER_ID)
val nodeId = controllerId.increment() val nodeId = controllerId.increment()
private var seq: Byte = 1 private var seq: Byte = 1
@ -24,7 +35,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
init { init {
val random = SecureRandom() val random = SecureRandom()
random.nextBytes(nonce) random.nextBytes(pdmNonce)
} }
fun negotiateLTKAndNonce(): LTK? { fun negotiateLTKAndNonce(): LTK? {
@ -41,9 +52,9 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
val podSps1 = msgIO.receiveMessage() val podSps1 = msgIO.receiveMessage()
aapsLogger.info(LTag.PUMPBTCOMM, "Received message: %s", podSps1) aapsLogger.info(LTag.PUMPBTCOMM, "Received message: %s", podSps1)
processSps1FromPod(podSps1) processSps1FromPod(podSps1)
// 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()
msgIO.sendMesssage(sps2.messagePacket) msgIO.sendMesssage(sps2.messagePacket)
@ -52,6 +63,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
val podSps2 = msgIO.receiveMessage() val podSps2 = msgIO.receiveMessage()
validatePodSps2(podSps2) validatePodSps2(podSps2)
seq++
// send SP0GP0 // send SP0GP0
msgIO.sendMesssage(sp0gp0().messagePacket) msgIO.sendMesssage(sp0gp0().messagePacket)
// read P0 // read P0
@ -83,7 +95,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
} }
private fun sps1(): PairMessage { private fun sps1(): PairMessage {
val publicKey = X25519.publicFromPrivate(privateKey) val publicKey = X25519.publicFromPrivate(pdmPrivate)
val payload = StringLengthPrefixEncoding.formatKeys( val payload = StringLengthPrefixEncoding.formatKeys(
arrayOf("SPS1="), arrayOf("SPS1="),
arrayOf(publicKey + nonce), arrayOf(publicKey + nonce),
@ -98,7 +110,11 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
private fun processSps1FromPod(msg: MessagePacket) { private fun processSps1FromPod(msg: MessagePacket) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS1 from pod: ${msg.payload.toHex()}") aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS1 from pod: ${msg.payload.toHex()}")
if (msg.payload.size != 48) {
throw MessageIOException()
}
podPublic = msg.payload.copyOfRange(0, PUBLIC_KEY_SIZE)
podNonce = msg.payload.copyOfRange(PUBLIC_KEY_SIZE, PUBLIC_KEY_SIZE+ NONCE_SIZE)
} }
private fun sps2(): PairMessage { private fun sps2(): PairMessage {
@ -124,8 +140,23 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
TODO("implement") TODO("implement")
} }
companion object {
fun generateKeys() {
val curveLTK = X25519.computeSharedSecret(pdmPrivate, podPublic)
aapsLogger.debug(LTag.PUMPBTCOMM, "LTK, donna key: ${curveLTK.toHex()}")
//first_key = data.pod_public[-4:] + data.pdm_public[-4:] + data.pod_nonce[-4:] + data.pdm_nonce[-4:]
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, "LTK, first key: ${firstKey.toHex()}")
}
companion object {
private val PUBLIC_KEY_SIZE = 32
private val NONCE_SIZE = 16
private val CONF_SIZE = 16
private 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 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.
} }
} }