diff --git a/source/USB Test App WPF/MainWindow.xaml.cs b/source/USB Test App WPF/MainWindow.xaml.cs index 1e3d9ac4..ed8b973a 100644 --- a/source/USB Test App WPF/MainWindow.xaml.cs +++ b/source/USB Test App WPF/MainWindow.xaml.cs @@ -27,6 +27,72 @@ namespace Serial_Test_App_WPF /// public partial class MainWindow : Window { + // Baltimore CyberTrust Root + // from https://cacert.omniroot.com/bc2025.crt + + // X509 RSA key PEM format 2048 bytes + private const string baltimoreCACertificate = +@"-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE-----"; + + // Let’s Encrypt Authority X3 (IdenTrust cross-signed) + // from https://letsencrypt.org/certificates/ + + // X509 RSA key PEM format 2048 bytes + private const string letsEncryptCACertificate = +@"-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1 +WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX +NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf +89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl +Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc +Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz +uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB +AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU +BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB +FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo +SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js +LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF +BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG +AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD +VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB +ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx +A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM +UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2 +DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1 +eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu +OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw +p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY +2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0 +ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR +PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b +rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt +-----END CERTIFICATE-----"; + + public MainWindow() { InitializeComponent(); @@ -757,10 +823,6 @@ private async void SetDeviceConfigButton_Click(object sender, RoutedEventArgs e) // get device info var deviceConfig = device.DebugEngine.GetDeviceConfiguration(cts.Token); - // change device configuration using the global configuration class - //deviceConfig.NetworkConfiguraton.MacAddress = new byte[] { 0, 0x80, 0xe1, 0x01, 0x35, 0x56 }; - //deviceConfig.NetworkConfiguraton.StartupAddressMode = DeviceConfiguration.AddressMode.DHCP; - // update new network configuration DeviceConfiguration.NetworkConfigurationProperties newDeviceNetworkConfiguration = new DeviceConfiguration.NetworkConfigurationProperties { @@ -774,16 +836,35 @@ private async void SetDeviceConfigButton_Click(object sender, RoutedEventArgs e) // write device configuration to device var returnValue = device.DebugEngine.UpdateDeviceConfiguration(newDeviceNetworkConfiguration, 0); - // add new wireless 802.11 configuration - DeviceConfiguration.Wireless80211ConfigurationProperties newWireless80211Configuration = new DeviceConfiguration.Wireless80211ConfigurationProperties() - { - Id = 44, - Ssid = "Nice_Ssid", - Password = "1234", - }; + //// add new wireless 802.11 configuration + //DeviceConfiguration.Wireless80211ConfigurationProperties newWireless80211Configuration = new DeviceConfiguration.Wireless80211ConfigurationProperties() + //{ + // Id = 44, + // Ssid = "Nice_Ssid", + // Password = "1234", + //}; + + //// write wireless configuration to device + //returnValue = device.DebugEngine.UpdateDeviceConfiguration(newWireless80211Configuration, 0); + + // build a CA certificate bundle + DeviceConfiguration.X509CaRootBundleProperties newX509CertificateBundle = new DeviceConfiguration.X509CaRootBundleProperties(); + + // add CA root certificates + + ///////////////////////////////////////////////////////// + // BECAUSE WE ARE PARSING FROM A BASE64 encoded format // + // NEED TO ADD A TERMINATOR TO THE STRING // + ///////////////////////////////////////////////////////// + + string caRootBundle = baltimoreCACertificate + letsEncryptCACertificate + "\0"; + + byte[] certificateRaw = Encoding.UTF8.GetBytes(caRootBundle); + + newX509CertificateBundle.Certificate = certificateRaw; - // write wireless configuration to device - returnValue = device.DebugEngine.UpdateDeviceConfiguration(newWireless80211Configuration, 0); + // write CA certificate to device + returnValue = device.DebugEngine.UpdateDeviceConfiguration(newX509CertificateBundle, 0); Debug.WriteLine(""); Debug.WriteLine(""); diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfiguration.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfiguration.cs index 290e96a1..380862ff 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfiguration.cs +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfiguration.cs @@ -35,6 +35,11 @@ public partial class DeviceConfiguration /// public static string MarkerConfigurationWireless80211AP_v1 = "AP1\0"; + /// + /// X509 CA Root bundle configuration marker + /// + public static string MarkerConfigurationX509CaRootBundle_v1 = "XB1\0"; + ///////////////////////////////////////////////////////////// /// @@ -47,19 +52,27 @@ public partial class DeviceConfiguration /// public List Wireless80211Configurations { get; set; } + /// + /// Collection of blocks in a target device. + /// + public List X509Certificates { get; set; } + public DeviceConfiguration() : this(new List(), - new List()) + new List(), + new List()) { } public DeviceConfiguration( List networkConfiguratons, - List networkWirelessConfiguratons + List networkWirelessConfiguratons, + List x509Certificates ) { NetworkConfigurations = networkConfiguratons; Wireless80211Configurations = networkWirelessConfiguratons; + X509Certificates = x509Certificates; } // operator to allow cast_ing a DeviceConfiguration object to DeviceConfigurationBase @@ -68,7 +81,8 @@ public static explicit operator DeviceConfigurationBase(DeviceConfiguration valu return new DeviceConfigurationBase() { NetworkConfigurations = value.NetworkConfigurations.Select(i => (NetworkConfigurationBase)i).ToArray(), - Wireless80211Configurations = value.Wireless80211Configurations.Select(i => (Wireless80211ConfigurationBase)i).ToArray() + Wireless80211Configurations = value.Wireless80211Configurations.Select(i => (Wireless80211ConfigurationBase)i).ToArray(), + X509CaRootBundle = value.X509Certificates.Select(i => (X509CaRootBundleBase)i).ToArray() }; } @@ -245,6 +259,41 @@ public static explicit operator Wireless80211ConfigurationBase(Wireless80211Conf } + + [AddINotifyPropertyChangedInterface] + public class X509CaRootBundleProperties : X509CaRootBundlePropertiesBase + { + public bool IsUnknown { get; set; } = true; + + public X509CaRootBundleProperties() + { + + } + + public X509CaRootBundleProperties(X509CaRootBundleBase certificate) + { + CertificateSize = (uint)certificate.Certificate.Length; + Certificate = certificate.Certificate; + + // reset unknown flag + IsUnknown = false; + } + + // operator to allow cast_ing a X509CaRootBundleBaseProperties object to X509CaRootBundleBase + public static explicit operator X509CaRootBundleBase(X509CaRootBundleProperties value) + { + var x509Certificate = new X509CaRootBundleBase() + { + Marker = Encoding.UTF8.GetBytes(MarkerConfigurationX509CaRootBundle_v1), + + CertificateSize = (uint)value.Certificate.Length, + Certificate = value.Certificate, + }; + + return x509Certificate; + } + } + ///////////////////////////////////////////////////////////// } diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationBase.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationBase.cs index 966d9522..7d5ae079 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationBase.cs +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationBase.cs @@ -11,5 +11,7 @@ public class DeviceConfigurationBase public NetworkConfigurationBase[] NetworkConfigurations; public Wireless80211ConfigurationBase[] Wireless80211Configurations { get; internal set; } + + public X509CaRootBundleBase[] X509CaRootBundle { get; internal set; } } } diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationOption.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationOption.cs index d4613ac2..d5c00c9b 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationOption.cs +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/DeviceConfigurationOption.cs @@ -31,6 +31,11 @@ public enum DeviceConfigurationOption : byte /// WirelessNetworkAP = 3, + /// + /// X509 Certificate block + /// + X509Certificate = 4, + /// /// All configuration blocks /// diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundleBase.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundleBase.cs new file mode 100644 index 00000000..d9ec0e7f --- /dev/null +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundleBase.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Tools.Debugger +{ + public class X509CaRootBundleBase + { + /// + /// This is the marker placeholder for this configuration block + /// 4 bytes length. + /// + public byte[] Marker; + + /// + /// Size of the certificate. + /// + public uint CertificateSize; + + /// + /// Certificate + /// + public byte[] Certificate; + + public X509CaRootBundleBase() + { + // need to init these here to match the expected size on the struct to be sent to the device + Marker = new byte[4]; + Certificate = new byte[64]; + } + } +} \ No newline at end of file diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundlePropertiesBase.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundlePropertiesBase.cs new file mode 100644 index 00000000..f84d3345 --- /dev/null +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/DeviceConfiguration/X509CaRootBundlePropertiesBase.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) 2018 The nanoFramework project contributors +// See LICENSE file in the project root for full license information. +// + +using PropertyChanged; + +namespace nanoFramework.Tools.Debugger +{ + [AddINotifyPropertyChangedInterface] + public class X509CaRootBundlePropertiesBase + { + private byte[] _certificate; + + public uint CertificateSize { get; set; } + + public byte[] Certificate + { + get => _certificate; + set + { + _certificate = value; + CertificateSize = (uint)value.Length; + } + } + } +} \ No newline at end of file diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Commands.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Commands.cs index 5c56d182..fe9beec3 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Commands.cs +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Commands.cs @@ -335,6 +335,23 @@ public void PrepareForDeserialize(int size, byte[] data, Converter converter) Password = new byte[64]; } } + + public class X509CaRootBundleConfig : X509CaRootBundleBase, IConverter + { + public X509CaRootBundleConfig() + { + Marker = new byte[4]; + CertificateSize = 0xFFFF; + Certificate = new byte[64]; + } + + public void PrepareForDeserialize(int size, byte[] data, Converter converter) + { + Marker = new byte[4]; + CertificateSize = 0xFFFF; + Certificate = new byte[size - 4 - 4]; + } + } } public class Monitor_UpdateConfiguration @@ -342,6 +359,7 @@ public class Monitor_UpdateConfiguration public uint Configuration; public uint BlockIndex; public uint Length = 0; + public uint Offset = 0; public byte[] Data = null; public class Reply @@ -349,12 +367,14 @@ public class Reply public uint ErrorCode; }; - public void PrepareForSend(byte[] data, int length) + public void PrepareForSend(byte[] data, int length, int offset = 0) { Length = (uint)length; Data = new byte[length]; - Array.Copy(data, 0, Data, 0, length); + Offset = (uint)offset; + + Array.Copy(data, offset, Data, 0, length); } } diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Engine.cs b/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Engine.cs index 2c8df383..5fce8d63 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Engine.cs +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/WireProtocol/Engine.cs @@ -3219,7 +3219,17 @@ public DeviceConfiguration GetDeviceConfiguration(CancellationToken cancellation return null; } - return new DeviceConfiguration(networkConfigs, networkWirelessConfigs); + // get all wireless network configuration blocks + var x509Certificates = GetAllX509Certificates(); + // check for cancellation request + if (cancellationToken.IsCancellationRequested) + { + // cancellation requested + Debug.WriteLine("cancellation requested"); + return null; + } + + return new DeviceConfiguration(networkConfigs, networkWirelessConfigs, x509Certificates); } public List GetAllNetworkConfigurations() @@ -3268,6 +3278,29 @@ public DeviceConfiguration GetDeviceConfiguration(CancellationToken cancellation return wireless80211Configurations; } + public List GetAllX509Certificates() + { + List x509Certificates = new List(); + + DeviceConfiguration.X509CaRootBundleProperties x509CertificatesProperties = null; + uint index = 0; + + do + { + // get next X509 certificate configuration block, if available + x509CertificatesProperties = GetX509CertificatesProperties(index++); + + // add to list, if valid + if(!x509CertificatesProperties.IsUnknown) + { + x509Certificates.Add(x509CertificatesProperties); + } + } + while (!x509CertificatesProperties.IsUnknown); + + return x509Certificates; + } + public DeviceConfiguration.NetworkConfigurationProperties GetNetworkConfiguratonProperties(uint configurationBlockIndex) { Debug.WriteLine("NetworkConfiguratonProperties"); @@ -3321,6 +3354,29 @@ public DeviceConfiguration.Wireless80211ConfigurationProperties GetWireless80211 return wirelessConfigProperties; } + public DeviceConfiguration.X509CaRootBundleProperties GetX509CertificatesProperties(uint configurationBlockIndex) + { + Debug.WriteLine("X509CertificateProperties"); + + IncomingMessage reply = GetDeviceConfiguration((uint)DeviceConfiguration.DeviceConfigurationOption.X509Certificate, configurationBlockIndex); + + Commands.Monitor_QueryConfiguration.X509CaRootBundleConfig x509Certificate = new Commands.Monitor_QueryConfiguration.X509CaRootBundleConfig(); + + DeviceConfiguration.X509CaRootBundleProperties x509CertificateProperties = new DeviceConfiguration.X509CaRootBundleProperties(); + + if (reply != null) + { + if (reply.Payload is Commands.Monitor_QueryConfiguration.Reply cmdReply && cmdReply.Data != null) + { + new Converter().Deserialize(x509Certificate, cmdReply.Data); + + x509CertificateProperties = new DeviceConfiguration.X509CaRootBundleProperties(x509Certificate); + } + } + + return x509CertificateProperties; + } + private IncomingMessage GetDeviceConfiguration(uint configuration, uint configurationBlockIndex) { Commands.Monitor_QueryConfiguration cmd = new Commands.Monitor_QueryConfiguration @@ -3341,6 +3397,7 @@ private IncomingMessage GetDeviceConfiguration(uint configuration, uint configur public bool UpdateDeviceConfiguration(DeviceConfiguration configuration) { bool okToUploadConfig = false; + Commands.Monitor_FlashSectorMap.FlashSectorData configSector = new Commands.Monitor_FlashSectorMap.FlashSectorData(); // the requirement to erase flash before storing is dependent on CLR capabilities which is only available if the device is running nanoCLR // when running nanoBooter those are not available @@ -3362,7 +3419,7 @@ public bool UpdateDeviceConfiguration(DeviceConfiguration configuration) } // get configuration sector details - var configSector = FlashSectorMap.FirstOrDefault(item => (item.m_flags & Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_MASK) == Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_CONFIG); + configSector = FlashSectorMap.FirstOrDefault(item => (item.m_flags & Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_MASK) == Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_CONFIG); // check if the device has a config sector if (configSector.m_NumBlocks > 0) @@ -3396,27 +3453,58 @@ public bool UpdateDeviceConfiguration(DeviceConfiguration configuration) // serialize the configuration block var configurationSerialized = CreateConverter().Serialize(((DeviceConfigurationBase)configuration)); - // prepare command to upload new configuration - Commands.Monitor_UpdateConfiguration cmd = new Commands.Monitor_UpdateConfiguration - { - Configuration = (uint)DeviceConfiguration.DeviceConfigurationOption.All - }; - cmd.PrepareForSend(configurationSerialized, configurationSerialized.Length); + // counters to manage the chunked update process + int count = configurationSerialized.Length; + int position = 0; - IncomingMessage reply = PerformSyncRequest(Commands.c_Monitor_UpdateConfiguration, 0, cmd); + // flag to signal the update operation success/failure + bool updateFailed = true; - if (reply != null) + while (count > 0) { - Commands.Monitor_UpdateConfiguration.Reply cmdReply = reply.Payload as Commands.Monitor_UpdateConfiguration.Reply; + Commands.Monitor_UpdateConfiguration cmd = new Commands.Monitor_UpdateConfiguration + { + Configuration = (uint)DeviceConfiguration.DeviceConfigurationOption.All + }; + + // get packet length, either the maximum allowed size or whatever is still available to TX + int packetLength = Math.Min((int)WireProtocolPacketSize, count); + + cmd.PrepareForSend(configurationSerialized, packetLength, position); + + IncomingMessage reply = PerformSyncRequest(Commands.c_Monitor_UpdateConfiguration, 0, cmd); - if (reply.IsPositiveAcknowledge() && cmdReply.ErrorCode == 0) + if (reply != null) { - return true; + Commands.Monitor_UpdateConfiguration.Reply cmdReply = reply.Payload as Commands.Monitor_UpdateConfiguration.Reply; + + if (!reply.IsPositiveAcknowledge() || cmdReply.ErrorCode != 0) + { + break; + } + + count -= packetLength; + position += packetLength; + + if(count == 0) + { + // update was OK, switch flag + updateFailed = false; + } } } - // write failed, try to replace back the old config? - // FIXME + if(updateFailed) + { + // failed to upload new configuration + // revert back old one + + // TODO + } + else + { + return true; + } } // default to false @@ -3469,15 +3557,27 @@ public bool UpdateDeviceConfiguration(T configuration, uint blockIndex) currentConfiguration.Wireless80211Configurations[(int)blockIndex] = configuration as DeviceConfiguration.Wireless80211ConfigurationProperties; } } + else if (configuration.GetType().Equals(typeof(DeviceConfiguration.X509CaRootBundleProperties))) + { + // if list is empty and request index is 0 + if (currentConfiguration.X509Certificates.Count == 0 && blockIndex == 0) + { + currentConfiguration.X509Certificates.Add(configuration as DeviceConfiguration.X509CaRootBundleProperties); + } + else + { + currentConfiguration.X509Certificates[(int)blockIndex] = configuration as DeviceConfiguration.X509CaRootBundleProperties; + } + } - if(UpdateDeviceConfiguration(currentConfiguration)) + if (UpdateDeviceConfiguration(currentConfiguration)) { // done here return true; } else { - // write failed, the old configuration is supposed to have been reverted by + // write failed, the old configuration it's supposed to have been reverted by now } } diff --git a/source/nanoFramework.Tools.DebugLibrary.Shared/nanoFramework.Tools.DebugLibrary.Net.projitems b/source/nanoFramework.Tools.DebugLibrary.Shared/nanoFramework.Tools.DebugLibrary.Net.projitems index 6b95b6c5..5b1fcb6e 100644 --- a/source/nanoFramework.Tools.DebugLibrary.Shared/nanoFramework.Tools.DebugLibrary.Net.projitems +++ b/source/nanoFramework.Tools.DebugLibrary.Shared/nanoFramework.Tools.DebugLibrary.Net.projitems @@ -17,6 +17,8 @@ + +