Skip to content

Commit bdb7643

Browse files
committed
Improve error handling
1 parent c5ac9a0 commit bdb7643

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

HomeKitDotNet/Controller.cs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using HomeKitDotNet.Models;
1616
using HomeKitDotNet.TLV;
1717
using HomeKitDotNet.TLV.Enums;
18+
using System.Globalization;
1819
using System.Net;
1920
using System.Numerics;
2021
using System.Security.Cryptography;
@@ -39,7 +40,7 @@ public Controller(out byte[] publicKey, out byte[] privateKey)
3940
{
4041
byte[] seed = RandomNumberGenerator.GetBytes(32);
4142
Ed25519.KeyPairFromSeed(out LTPK, out LTSK, seed);
42-
deviceID = RandomNumberGenerator.GetBytes(16);
43+
deviceID = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture));
4344
publicKey = LTPK;
4445
privateKey = LTSK;
4546
}
@@ -52,6 +53,12 @@ public Controller(out byte[] publicKey, out byte[] privateKey)
5253
/// <param name="deviceID"></param>
5354
public Controller(byte[] privateKey, byte[] publicKey, byte[] deviceID)
5455
{
56+
if (privateKey.Length != 64)
57+
throw new ArgumentException("Invalid Private Key Length: " + privateKey.Length);
58+
if (publicKey.Length != 32)
59+
throw new ArgumentException("Invalid Public Key Length: " + publicKey.Length);
60+
if (deviceID.Length != 36)
61+
throw new ArgumentException("Invalid Device ID Length: " + deviceID.Length);
5562
LTPK = publicKey;
5663
LTSK = privateKey;
5764
this.deviceID = deviceID;
@@ -168,44 +175,48 @@ public async Task<bool> UnPair(HomeKitEndPoint endpoint)
168175
/// <param name="destination"></param>
169176
/// <returns></returns>
170177
/// <exception cref="IOException"></exception>
178+
/// <exception cref="UnauthorizedAccessException"></exception>
171179
public async Task<AccessoryInfo> Pair(long setupPin, IPEndPoint destination)
172180
{
173181
string I = "Pair-Setup";
174182
string P = setupPin.ToString("000-00-000");
175183

176184
Connection con = new Connection(destination);
177185

178-
Console.WriteLine("LTPK: " + BitConverter.ToString(LTPK));
179-
Console.WriteLine("LTSK: " + BitConverter.ToString(LTSK));
180-
181186
//Step 1
182187
HttpResponseMessage msg = await con.Post("/pair-setup", new TLVInt(TLVType.kTLVType_State, (byte)PairingState.M1), new TLVInt(TLVType.kTLVType_Method, (byte)Method.PairSetupWithAuth));
183188
if (!msg.IsSuccessStatusCode)
184-
throw new IOException($"Pair Step 1 Failed with {msg.StatusCode}: {msg.ReasonPhrase}");
189+
throw new IOException($"Pair Step 2 Failed with {msg.StatusCode}: {msg.ReasonPhrase}");
185190
List<TLVValue> responseTLVs = TLVValue.CollectionFromStream(msg.Content.ReadAsStream());
186191

187192
//Step 3
188-
byte[] bytes = TLVValue.Concat(TLVType.kTLVType_PublicKey, responseTLVs);
189-
BigInteger B = new BigInteger(bytes, true, true);
193+
byte[] accessoryPK = TLVValue.Concat(TLVType.kTLVType_PublicKey, responseTLVs);
194+
if (accessoryPK.Length == 0)
195+
throw new IOException($"Pair Step 3 Failed - Public key is missing");
196+
if (responseTLVs.Any(t => t.Type == TLVType.kTLVType_Error))
197+
throw new IOException("Received M2 Error");
198+
BigInteger B = new BigInteger(accessoryPK, true, true);
190199
byte[] s = (responseTLVs.Find(t => t.Type == TLVType.kTLVType_Salt) as TLVBytes)!.Value;
191200
SRP srp = new SRP();
192201
BigInteger A = srp.GenerateAValues();
193202
BigInteger K = srp.ComputeSessionKey(I, P, s, B);
194203
BigInteger M1 = srp.GenerateClientProof(I, s, A, B, K);
195-
msg = await con.Post("/pair-setup", [
204+
msg = await con.Post("/pair-setup",
196205
new TLVInt(TLVType.kTLVType_State, (byte)PairingState.M3),
197206
new TLVBytes(TLVType.kTLVType_PublicKey, A.ToByteArray(true, true)),
198207
new TLVBytes(TLVType.kTLVType_Proof, M1.ToByteArray(true, true))
199-
]);
208+
);
200209

201210
if (!msg.IsSuccessStatusCode)
202211
{
203212
string content = new StreamReader(msg.Content.ReadAsStream()).ReadToEnd();
204-
throw new IOException($"Pair Step 3 Failed with {msg.StatusCode}: {msg.ReasonPhrase}: {content}");
213+
throw new IOException($"Pair Step 4 Failed with {msg.StatusCode}: {msg.ReasonPhrase}: {content}");
205214
}
206215

207216
//Step 5
208217
responseTLVs = TLVValue.CollectionFromStream(msg.Content.ReadAsStream());
218+
if (responseTLVs.Any(t => t.Type == TLVType.kTLVType_Error))
219+
throw new UnauthorizedAccessException("Invalid PIN Code");
209220
BigInteger M2 = new BigInteger((responseTLVs.Find(t => t.Type == TLVType.kTLVType_Proof) as TLVBytes)!.Value, true, true);
210221
bool valid = srp.ValidateServerProof(M2, M1, K);
211222

@@ -229,10 +240,10 @@ public async Task<AccessoryInfo> Pair(long setupPin, IPEndPoint destination)
229240
encrypter.Encrypt(Encoding.ASCII.GetBytes("\0\0\0\0PS-Msg05"), encryptionPayload.ToArray(), encryptedPayload.AsSpan().Slice(0, (int)encryptionPayload.Length), encryptedPayload.AsSpan().Slice((int)encryptionPayload.Length, 16));
230241
}
231242

232-
msg = await con.Post("/pair-setup", [
243+
msg = await con.Post("/pair-setup",
233244
new TLVInt(TLVType.kTLVType_State, (byte)PairingState.M5),
234245
new TLVBytes(TLVType.kTLVType_EncryptedData, encryptedPayload)
235-
]);
246+
);
236247

237248
if (!msg.IsSuccessStatusCode)
238249
{

HomeKitDotNet/TLV/Enums/Method.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public enum Method : byte
1919
PairVerify = 0x2,
2020
AddPairing = 0x3,
2121
RemovePairing = 0x4,
22-
ListPairings = 0x5
22+
ListPairings = 0x5,
23+
PairResume = 0x6,
2324
}
2425
}

HomeKitDotNet/logo.png

-419 Bytes
Loading

0 commit comments

Comments
 (0)