Beispiel #1
0
        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;
        }
Beispiel #3
0
        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)));
        }
Beispiel #5
0
        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);
        }