1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-20 12:00:51 +02:00

[Huawei] Add new Crypto and authMode

This commit is contained in:
Damien 'Psolyca' Gaignon 2024-01-29 21:51:45 +01:00
parent f759072a7c
commit 86461ada1a
No known key found for this signature in database
GPG Key ID: 9E9404E5D9E11843
6 changed files with 42 additions and 31 deletions

View File

@ -24,6 +24,7 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
@ -78,15 +79,17 @@ public class HuaweiCrypto {
public static final long ENCRYPTION_COUNTER_MAX = 0xFFFFFFFF;
protected int authVersion;
protected boolean isHiChainLite = false;
protected int authMode;
protected byte authAlgo;
public HuaweiCrypto(int authVersion) {
this.authVersion = authVersion;
}
public HuaweiCrypto(int authVersion, boolean isHiChainLite) {
public HuaweiCrypto(int authVersion, byte authAlgo, int authMode) {
this(authVersion);
this.isHiChainLite = isHiChainLite;
this.authMode = authMode;
this.authAlgo = authAlgo;
}
public static byte[] generateNonce() {
@ -115,26 +118,27 @@ public class HuaweiCrypto {
return CryptoUtils.calcHmacSha256(digestStep1, nonce);
}
public byte[] computeDigestHiChainLite(byte[] message, byte[] key, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException {
public byte[] computeDigestHiChainLite(byte[] message, byte[] key, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
byte[] digestStep1;
byte[] hashKey = CryptoUtils.digest(key);
byte[] digestSecret = getDigestSecret();
for (int i = 0; i < digestSecret.length; i++) {
digestSecret[i] = (byte) (((0xFF & hashKey[i]) ^ (digestSecret[i] & 0xFF)) & 0xFF);
}
// 2 possibilities:
// - type 1 : Pbk (SDK_INT>= 0x17) fallback to MacSha
// - type 2 : MacSha
// We force type 2 to avoid a new calculation
byte[] msgToDigest = ByteBuffer.allocate(18)
.put(digestSecret)
.put(message)
.array();
byte[] digestStep1 = CryptoUtils.calcHmacSha256(msgToDigest, nonce) ;
if (authAlgo == 0x01) {
digestStep1 = CryptoUtils.pbkdf2Sha256(msgToDigest, nonce, 0x3e8, 0x100);
} else {
digestStep1 = CryptoUtils.calcHmacSha256(msgToDigest, nonce);
}
return CryptoUtils.calcHmacSha256(digestStep1, nonce);
}
public byte[] digestChallenge(byte[] secretKey, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException {
if (isHiChainLite) {
public byte[] digestChallenge(byte[] secretKey, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
if (authMode == 0x02) {
if (secretKey == null)
return null;
if (authVersion == 0x02) {
@ -149,8 +153,8 @@ public class HuaweiCrypto {
return computeDigest(MESSAGE_CHALLENGE, nonce);
}
public byte[] digestResponse(byte[] secretKey, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException {
if (isHiChainLite) {
public byte[] digestResponse(byte[] secretKey, byte[] nonce) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
if (authMode == 0x02) {
if (secretKey == null)
return null;
if (authVersion == 0x02) {

View File

@ -55,6 +55,7 @@ public class HuaweiPacket {
protected byte[] pinCode = null;
protected byte interval;
protected byte authAlgo;
public void setAuthVersion(byte authVersion) {
this.authVersion = authVersion;
@ -134,6 +135,14 @@ public class HuaweiPacket {
public void setEncryptionCounter(long counter) {
this.encryptionCounter = counter;
}
public void setAuthAlgo(byte authAlgo) {
this.authAlgo = authAlgo;
}
public byte getAuthAlgo () {
return this.authAlgo;
}
}
public static abstract class ParseException extends Exception {

View File

@ -625,8 +625,7 @@ public class DeviceConfig {
public Request(
ParamsProvider paramsProvider,
byte[] challenge,
byte[] nonce,
boolean isHiChainLite
byte[] nonce
) {
super(paramsProvider);
@ -636,8 +635,8 @@ public class DeviceConfig {
this.tlv = new HuaweiTLV()
.put(0x01, challenge)
.put(0x02, nonce);
if (isHiChainLite)
this.tlv.put(0x03, (byte)0x02); // Force type 2
if (paramsProvider.getAuthMode() == 0x02)
this.tlv.put(0x03, paramsProvider.getAuthAlgo());
this.isEncrypted = false;
this.complete = true;
}

View File

@ -376,7 +376,7 @@ public class HuaweiSupportProvider {
protected void initializeDeviceHiChainLiteMode(Request linkParamsReq) {
try {
createSecretKey();
GetAuthRequest authReq = new GetAuthRequest(this, linkParamsReq, true);
GetAuthRequest authReq = new GetAuthRequest(this, linkParamsReq);
GetBondParamsRequest bondParamsReq = new GetBondParamsRequest(this);
GetBondRequest bondReq = new GetBondRequest(this);
authReq.nextRequest(bondParamsReq);

View File

@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.List;
@ -36,9 +37,10 @@ public class GetAuthRequest extends Request {
protected final byte[] clientNonce;
protected short authVersion;
protected boolean isHiChainLite = false;
protected byte authAlgo;
protected byte[] doubleNonce;
protected byte[] key = null;
protected byte authMode;
public GetAuthRequest(HuaweiSupportProvider support,
Request linkParamsReq) {
@ -51,22 +53,17 @@ public class GetAuthRequest extends Request {
.put(clientNonce)
.array();
this.authVersion = paramsProvider.getAuthVersion();
}
public GetAuthRequest(HuaweiSupportProvider support,
Request linkParamsReq,
boolean isHiChainLite) {
this(support, linkParamsReq);
this.isHiChainLite = isHiChainLite;
this.authAlgo = paramsProvider.getAuthAlgo();
this.authMode = paramsProvider.getAuthMode();
}
@Override
protected List<byte[]> createRequest() throws RequestCreationException {
huaweiCrypto = new HuaweiCrypto(authVersion, isHiChainLite);
huaweiCrypto = new HuaweiCrypto(authVersion, authAlgo, authMode);
byte[] nonce;
try {
if (isHiChainLite) {
if (authMode == 0x02) {
key = paramsProvider.getPinCode();
if (authVersion == 0x02)
key = paramsProvider.getSecretKey();
@ -78,10 +75,10 @@ public class GetAuthRequest extends Request {
byte[] challenge = huaweiCrypto.digestChallenge(key, doubleNonce);
if (challenge == null)
throw new RequestCreationException("Challenge null");
return new DeviceConfig.Auth.Request(paramsProvider, challenge, nonce, isHiChainLite).serialize();
return new DeviceConfig.Auth.Request(paramsProvider, challenge, nonce).serialize();
} catch (HuaweiPacket.CryptoException e) {
throw new RequestCreationException(e);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException e) {
throw new RequestCreationException("Digest exception", e);
}
}
@ -105,7 +102,7 @@ public class GetAuthRequest extends Request {
+ StringUtils.bytesToHex(expectedAnswer)
);
}
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException e) {
throw new ResponseParseException("Challenge response digest exception");
}
}

View File

@ -82,5 +82,7 @@ public class GetLinkParamsRequest extends Request {
paramsProvider.setAuthVersion(((LinkParams.Response) receivedPacket).authVersion);
this.bondState = ((LinkParams.Response) receivedPacket).bondState;
paramsProvider.setAuthAlgo(((LinkParams.Response) receivedPacket).authAlgo);
}
}