static internal void DoDemo(int numDevices) { Program.IODir += "MultiDevice/"; CertMaker m = new CertMaker(Program.IODir); IoTDevice[] deviceList = new IoTDevice[numDevices]; HubController = new HubControl(); // make the devices and enroll them in the hub for (int j = 0; j < numDevices; j++) { string devId = GetDeviceID(j); Program.SetDeviceNumber(j); int fwidSeed = 0; m.MakeNew(5, false, fwidSeed); HubController.Connect(); HubController.RemoveDevice(devId); var devInfo = ExtensionDecoder.Decode(Program.ToPath(Program.AliasCert)); HubController.EnrollDevice(devId, fwidSeed, Helpers.Hexify(devInfo.FirmwareID), devInfo.Cert.Thumbprint); IoTDevice device = new IoTDevice(devId, 0, j); deviceList[j] = device; } // run through messaging and update bool[] primaryOrSEcondary = new bool[numDevices]; int epoch = 0; while (true) { for (int j = 0; j < numDevices; j++) { Program.SetDeviceNumber(j); var device = deviceList[j]; string devId = GetDeviceID(j); // send messages using current firmware device.RefreshCert(); device.SendMessages(1, 30); if (device.FirmwareUpdateNeeded) { // update the firmware on the device int fwidSeed = device.DesiredFwVersionNumber; m.MakeAliasCert(true, fwidSeed); var devInfo = ExtensionDecoder.Decode(Program.ToPath(Program.AliasCert)); // and tell the hub HubController.RefreshDevice(devId, fwidSeed, Helpers.Hexify(devInfo.FirmwareID), devInfo.Cert.Thumbprint, primaryOrSEcondary[j]); primaryOrSEcondary[j] = !primaryOrSEcondary[j]; device.CurrentFwVersionNumber = fwidSeed; } } Debug.WriteLine($"Epoch == {epoch++}"); } }
void QueryFWStatus() { try { var twin = Me.GetTwinAsync().Result; var myFwid = Helpers.Hexify(Helpers.HashData(new byte[] { (byte)CurrentFwVersionNumber }, 0, 1)); var targetFwVersionNumber = twin.Properties.Desired["VersionNumber"]; Int64 currentReportedVersionNumber = -1; if (twin.Properties.Reported.Contains("VersionNumber")) { currentReportedVersionNumber = (Int64)twin.Properties?.Reported["VersionNumber"]; } // update our version number if hub version number is not current if (currentReportedVersionNumber < 0 || CurrentFwVersionNumber != currentReportedVersionNumber || updateCurrentVersionNumber ) { TwinCollection t = new TwinCollection(); t["VersionNumber"] = CurrentFwVersionNumber; Me.UpdateReportedPropertiesAsync(t).Wait(); updateCurrentVersionNumber = false; } // if the target version number is not current, then flag that we need a FW update if (targetFwVersionNumber != CurrentFwVersionNumber.ToString()) { FirmwareUpdateNeeded = true; DesiredFwVersionNumber = targetFwVersionNumber; Debug.WriteLine("Need to update myself"); } else { FirmwareUpdateNeeded = false; Debug.WriteLine("Firmware version is good"); } // am I p0wned? If I'm P0wned I won't update myself if (twin.Properties.Desired.Contains("POwned")) { P0wned = (bool)twin.Properties?.Desired["POwned"]; } } catch (Exception e) { Debug.WriteLine("Error querying status" + e.ToString()); throw; } return; }
internal static void SetCertForPort(string certFile, int port) { X509Certificate2 serverCert = new X509Certificate2(certFile); var certHashString = Helpers.Hexify(serverCert.GetCertHash()); var psi = new ProcessStartInfo("netsh"); psi.Arguments = $"http add sslcert ccs=5556 certhash={certHashString} appid={{00112233-4455-6677-8899-AABBCCDDEEFF}}"; psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.RedirectStandardError = true; var proc = Process.Start(psi);; string op = proc.StandardError.ReadToEnd(); proc.WaitForExit(); }
void AddRIoTExtension(X509V3CertificateGenerator certGen, byte[] fwid, AsymmetricCipherKeyPair devIdKey) { DerObjectIdentifier extensionTag = new DerObjectIdentifier(Program.DeviceIdOid); DerOctetString fwId = new DerOctetString(fwid); var TaggedDevID = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(devIdKey.Public); // {hashAlgId,fwidHash} var TaggedFWID = new DerSequence( new Asn1Encodable[] { NistObjectIdentifiers.IdSha256, new DerOctetString(fwid) }); // {1, devId, fwId} var EncodedRIoTIdentity = new DerSequence( new Asn1Encodable[] { new DerInteger(1), // version number TaggedDevID, TaggedFWID }); // {riotOid, encodedIdentity} var TaggedEncodedRIoTID = new DerSequence( new Asn1Encodable[] { new DerObjectIdentifier(Program.DeviceIdOid), EncodedRIoTIdentity }); byte[] ttt = TaggedEncodedRIoTID.GetDerEncoded(); Debug.WriteLine(Helpers.Hexify(ttt)); Debug.WriteLine(Asn1Dump.DumpAsString(TaggedEncodedRIoTID)); certGen.AddExtension( X509Extensions.SubjectAlternativeName.Id, true, new GeneralNames( new GeneralName(GeneralName.OtherName, TaggedEncodedRIoTID))); }
private static void ProcessClient(TcpClient client, bool chat) { SslStream sslStream = new SslStream(client.GetStream(), false, ValidateDeviceCertificate); try { // authenticate as server and request client cert. This invokes the ValidateDeviceCertificate // callback. If the callback returns false (or there are other errors), AuthenticateAsServer // throws an exception sslStream.AuthenticateAsServer(ServerCert, true, SslProtocols.Tls, false); // if we get to here, all TLS+RIoT checks have succeeded. // Print info about the connected device var deviceCert = sslStream.RemoteCertificate; var devCert2 = new X509Certificate2(deviceCert); var info = ExtensionDecoder.Decode(devCert2); if (info == null) { // should not happen since the cert has already been // validated in the callback.. Helpers.Notify("Unexpected missing or malformed RIoT device certificate", true); return; } // we have a good device: tell the world Helpers.Notify($"RIoT Device Connected:"); Helpers.Notify($" DeviceID:{Helpers.Hexify(info.EncodedDeviceIDKey).Substring(0, 60) + "..."}"); Helpers.Notify($" FWID:{Helpers.Hexify(info.FirmwareID)}"); if (chat) { // Read a message from the client. sslStream.ReadTimeout = 10000; sslStream.WriteTimeout = 10000; Helpers.Notify("Waiting for client message..."); if (DeviceIDPEMFile != null) { string messageData = ReadMessageX(sslStream); Helpers.Notify($"Server received: {messageData}"); // Write a message to the client. byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>"); Helpers.Notify("Sending hello message."); sslStream.Write(message); } else { ProcessFakeDRSMessage(sslStream); } } // give the client some time to process before closing the stream Thread.Sleep(30); } catch (AuthenticationException e) { Helpers.Notify($"Exception in AuthenticateAs server block: {e.Message}", true); if (e.InnerException != null) { Helpers.Notify($"Inner exception: {e.InnerException.Message}", true); } Helpers.Notify("Authentication failed - closing the connection.", true); sslStream.Close(); client.Close(); return; } finally { Helpers.Notify("Client has disconnected. Stream is closing"); sslStream.Close(); client.Close(); } }
/// <summary> /// Make a new Alias Cert. If refresh=false, a new DevID and Alias are created. If refresh=true /// then just the Alias is created and re-certified using the stored DevID key. /// </summary> /// <param name="refresh"></param> /// <returns></returns> internal DeviceBundle MakeAliasCert(bool refresh, int fwidSeed) { DateTime now = DateTime.Now; byte[] fwid = Helpers.HashData(new byte[1] { (byte)fwidSeed }, 0, 1); const int keyStrength = 256; CryptoApiRandomGenerator rg = new CryptoApiRandomGenerator(); SecureRandom random = new SecureRandom(rg); KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, keyStrength); var keyPairGenerator = new ECKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); AsymmetricCipherKeyPair devIdKey = null; if (refresh) { devIdKey = (AsymmetricCipherKeyPair)Helpers.ReadPemObject(ToPath(Program.DeviceIDPrivate)); } else { devIdKey = keyPairGenerator.GenerateKeyPair(); } // test - remove var oids = new List <Object>() { X509Name.UnstructuredName }; var values = new List <Object>() { "ljkljljklkjlkjlkjlkjlkjlkjlkjlkjlkjljklkjlkjlkjlkjljk" }; X509Name name = new X509Name(oids, values); AsymmetricCipherKeyPair aliasKey = keyPairGenerator.GenerateKeyPair(); // make a string name based on DevID public. Note that the authoritative information // is encoded in the RIoT-extension: this is just for quick-and-dirty device identification. var pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(devIdKey.Public); byte[] pubEncoded = pubInfo.GetDerEncoded(); var pubHashed = Helpers.HashData(pubEncoded, 0, pubEncoded.Length); var shortNameBytes = Helpers.CopyArray(pubHashed, 0, 8); var shortNameString = Helpers.Hexify(shortNameBytes); X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); var serialNumber = new byte[8]; rg.NextBytes(serialNumber); serialNumber[0] &= 0x7F; certGen.SetSerialNumber(new BigInteger(serialNumber)); // The important name-related stuff is encoded in the RIoT extension certGen.SetIssuerDN(new X509Name($"CN=[I]DevID:{shortNameString}, O=MSR_TEST, C=US")); // test REMOVE //certGen.SetSubjectDN(name); certGen.SetSubjectDN(new X509Name($"CN=[S]DevID:{shortNameString}, O=MSR_TEST, C=US")); certGen.SetNotBefore(now); certGen.SetNotAfter(now + new TimeSpan(365 * 10, 0, 0, 0, 0)); certGen.SetPublicKey(aliasKey.Public); // Add the extensions (todo: not sure about KeyUsage.DigitalSiganture certGen.AddExtension(X509Extensions.ExtendedKeyUsage, true, ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.IdKPClientAuth))); certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature)); AddRIoTExtension(certGen, fwid, devIdKey); // sign it ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA", devIdKey.Private, random); var certificate = certGen.Generate(signatureFactory); // and return the bundle DeviceBundle bundle = new DeviceBundle { AliasCert = certificate, DeviceIDPublic = devIdKey.Public, AliasKeyPair = aliasKey }; // Just the AliasCert Helpers.WritePEMObject(ToPath(Program.AliasCert), bundle.AliasCert); // The Alias Key Pair Helpers.WritePEMObject(ToPath(Program.AliasKey), bundle.AliasKeyPair); // The encoded DevID Helpers.WritePEMObject(ToPath(Program.DeviceIDPublic), bundle.DeviceIDPublic); // DeviceIDPrivate (just for the update demo) Helpers.WritePEMObject(ToPath(Program.DeviceIDPrivate), devIdKey.Private); return(bundle); }