mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-28 03:25:49 +01:00
Mi Band 6 auth: add test, fix crypto
This commit is contained in:
parent
d352624629
commit
2c06e5d39c
@ -767,6 +767,14 @@ int ecdh_shared_secret(const uint8_t* private_key, const uint8_t* others_pub, ui
|
|||||||
output[i] = others_pub[i];
|
output[i] = others_pub[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear bits > CURVE_DEGREE in highest word to satisfy constraint 1 <= exp < n. */
|
||||||
|
int nbits = bitvec_degree(base_order);
|
||||||
|
|
||||||
|
for (int i = (nbits - 1); i < (BITVEC_NWORDS * 32); ++i)
|
||||||
|
{
|
||||||
|
bitvec_clr_bit((uint32_t*)private_key, i);
|
||||||
|
}
|
||||||
|
|
||||||
/* Multiply other side's public key with own private key */
|
/* Multiply other side's public key with own private key */
|
||||||
gf2point_mul((uint32_t*)output,(uint32_t*)(output + BITVEC_NBYTES), (const uint32_t*)private_key);
|
gf2point_mul((uint32_t*)output,(uint32_t*)(output + BITVEC_NBYTES), (const uint32_t*)private_key);
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -36,7 +35,6 @@ import javax.crypto.IllegalBlockSizeException;
|
|||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
@ -45,12 +43,12 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
public class InitOperation2021 extends InitOperation {
|
public class InitOperation2021 extends InitOperation {
|
||||||
private final byte[] privateEC = new byte[24];
|
private byte[] privateEC = new byte[24];
|
||||||
private byte[] publicEC;
|
private byte[] publicEC;
|
||||||
private byte[] remotePublicEC = new byte[48];
|
private byte[] remotePublicEC = new byte[48];
|
||||||
private byte[] remoteRandom = new byte[16];
|
private final byte[] remoteRandom = new byte[16];
|
||||||
private byte[] sharedEC;
|
private byte[] sharedEC;
|
||||||
private byte[] finalSharedSessionAES = new byte[16];
|
private final byte[] finalSharedSessionAES = new byte[16];
|
||||||
|
|
||||||
private final byte[] reassembleBuffer = new byte[512];
|
private final byte[] reassembleBuffer = new byte[512];
|
||||||
private int lastSequenceNumber = 0;
|
private int lastSequenceNumber = 0;
|
||||||
@ -68,6 +66,23 @@ public class InitOperation2021 extends InitOperation {
|
|||||||
super(needsAuth, authFlags, cryptFlags, support, builder);
|
super(needsAuth, authFlags, cryptFlags, support, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testAuth() {
|
||||||
|
byte[] secretKey = getSecretKey();
|
||||||
|
privateEC = new byte[]{0x0b, 0x42, (byte) 0xb9, (byte) 0xe6, 0x1c, 0x23, 0x34, 0x0e, 0x35, (byte) 0xc1, 0x6e, 0x2e, 0x7d, (byte) 0xe4, 0x33, (byte) 0xf4, (byte) 0xb5, (byte) 0x85, (byte) 0x9a, 0x72, (byte) 0xec, 0x11, 0x40, 0x27};
|
||||||
|
remotePublicEC = new byte[]{(byte) 0xe6, 0x01, 0x6a, (byte) 0xba, 0x1d, (byte) 0xe7, (byte) 0xac, 0x0f, 0x0c, 0x7f, 0x0f, (byte) 0xf7, (byte) 0xe2, 0x24, 0x3e, 0x66, 0x62, (byte) 0xb5, (byte) 0xe0, 0x3b, 0x01, 0x00, 0x00, 0x00, (byte) 0xad, (byte) 0x8a, 0x4b, (byte) 0xed, (byte) 0xc7, 0x6a, 0x1e, (byte) 0xfd, (byte) 0xe7, 0x72, 0x5c, (byte) 0xc6, 0x62, (byte) 0xb5, 0x48, 0x35, 0x51, 0x3e, 0x3d, 0x57, 0x05, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
|
publicEC = ecdh_generate_public(privateEC);
|
||||||
|
sharedEC = ecdh_generate_shared(privateEC, remotePublicEC);
|
||||||
|
LOG.warn("publicEC: " + GB.hexdump(publicEC));
|
||||||
|
LOG.warn("privateEC: " + GB.hexdump(privateEC));
|
||||||
|
LOG.warn("remotepubEC: " + GB.hexdump(remotePublicEC));
|
||||||
|
LOG.warn("sharedEC: " + GB.hexdump(sharedEC));
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
finalSharedSessionAES[i] = (byte) (sharedEC[i + 8] ^ secretKey[i]);
|
||||||
|
}
|
||||||
|
LOG.warn("finalSharedAES: " + GB.hexdump(finalSharedSessionAES));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doPerform() {
|
protected void doPerform() {
|
||||||
huamiSupport.enableNotifications(builder, true);
|
huamiSupport.enableNotifications(builder, true);
|
||||||
@ -80,6 +95,7 @@ public class InitOperation2021 extends InitOperation {
|
|||||||
sendPubkeyCommand[2] = 0x00;
|
sendPubkeyCommand[2] = 0x00;
|
||||||
sendPubkeyCommand[3] = 0x02;
|
sendPubkeyCommand[3] = 0x02;
|
||||||
System.arraycopy(publicEC, 0, sendPubkeyCommand, 4, 48);
|
System.arraycopy(publicEC, 0, sendPubkeyCommand, 4, 48);
|
||||||
|
//testAuth();
|
||||||
huamiSupport.writeToChunked2021(builder, (short) 0x82, (byte) 0x66, sendPubkeyCommand);
|
huamiSupport.writeToChunked2021(builder, (short) 0x82, (byte) 0x66, sendPubkeyCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +121,6 @@ public class InitOperation2021 extends InitOperation {
|
|||||||
UUID characteristicUUID = characteristic.getUuid();
|
UUID characteristicUUID = characteristic.getUuid();
|
||||||
if (HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ.equals(characteristicUUID)) {
|
if (HuamiService.UUID_CHARACTERISTIC_CHUNKEDTRANSFER_2021_READ.equals(characteristicUUID)) {
|
||||||
byte[] value = characteristic.getValue();
|
byte[] value = characteristic.getValue();
|
||||||
// 0x03 0x01 0x00 0x64 0x00 0x43 0x00 0x00 0x00 0x82 0x00 0x10 0x04 0x01 0x36 0x41 0xf2 0x5a 0x8f 0xb3
|
|
||||||
if (value.length > 1 && value[0] == 0x03) {
|
if (value.length > 1 && value[0] == 0x03) {
|
||||||
int sequenceNumber = value[4];
|
int sequenceNumber = value[4];
|
||||||
int headerSize;
|
int headerSize;
|
||||||
@ -120,6 +135,20 @@ public class InitOperation2021 extends InitOperation {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
headerSize = 5;
|
headerSize = 5;
|
||||||
|
} else if (value[9] == (byte) 0x82 && value[10] == 0x00 && value[11] == 0x10 && value[12] == 0x05 && value[13] == 0x01) {
|
||||||
|
try {
|
||||||
|
TransactionBuilder builder = createTransactionBuilder("Authenticated, now initialize phase 2");
|
||||||
|
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||||
|
huamiSupport.enableFurtherNotifications(builder, true);
|
||||||
|
huamiSupport.requestDeviceInfo(builder);
|
||||||
|
huamiSupport.phase2Initialize(builder);
|
||||||
|
huamiSupport.phase3Initialize(builder);
|
||||||
|
huamiSupport.setInitialized(builder);
|
||||||
|
huamiSupport.performImmediately(builder);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("faild initializing device", e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||||
return super.onCharacteristicChanged(gatt, characteristic);
|
return super.onCharacteristicChanged(gatt, characteristic);
|
||||||
@ -132,12 +161,17 @@ public class InitOperation2021 extends InitOperation {
|
|||||||
lastSequenceNumber = sequenceNumber;
|
lastSequenceNumber = sequenceNumber;
|
||||||
if (reassembleBuffer_pointer == reassembleBuffer_expectedBytes) {
|
if (reassembleBuffer_pointer == reassembleBuffer_expectedBytes) {
|
||||||
System.arraycopy(reassembleBuffer, 0, remoteRandom, 0, 16);
|
System.arraycopy(reassembleBuffer, 0, remoteRandom, 0, 16);
|
||||||
|
LOG.info("remoteRandom: " + GB.hexdump(remoteRandom));
|
||||||
System.arraycopy(reassembleBuffer, 16, remotePublicEC, 0, 48);
|
System.arraycopy(reassembleBuffer, 16, remotePublicEC, 0, 48);
|
||||||
|
LOG.info("remotePublicEC: " + GB.hexdump(remotePublicEC));
|
||||||
sharedEC = ecdh_generate_shared(privateEC, remotePublicEC);
|
sharedEC = ecdh_generate_shared(privateEC, remotePublicEC);
|
||||||
|
LOG.info("sharedEC: " + GB.hexdump(sharedEC));
|
||||||
|
|
||||||
byte[] secretKey = getSecretKey();
|
byte[] secretKey = getSecretKey();
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
finalSharedSessionAES[i] = (byte) (sharedEC[i + 8] ^ secretKey[i]);
|
finalSharedSessionAES[i] = (byte) (sharedEC[i + 8] ^ secretKey[i]);
|
||||||
}
|
}
|
||||||
|
LOG.info("sharedSessionAES: " + GB.hexdump(finalSharedSessionAES));
|
||||||
try {
|
try {
|
||||||
byte[] encryptedRandom1 = encryptAES(remoteRandom, secretKey);
|
byte[] encryptedRandom1 = encryptAES(remoteRandom, secretKey);
|
||||||
byte[] encryptedRandom2 = encryptAES(remoteRandom, finalSharedSessionAES);
|
byte[] encryptedRandom2 = encryptAES(remoteRandom, finalSharedSessionAES);
|
||||||
|
Loading…
Reference in New Issue
Block a user