Skip to content

Commit

Permalink
Work on configuration block implementation
Browse files Browse the repository at this point in the history
- Add support for nanoframework/nf-debugger#173.
- Improve Monitor_UpdateConfiguration command to handle configuration blocks larger then the WP buffer size.
- Add new configuration block to store X509 CA Root certificate bundles.
- Tested for STM32.
- **WIP for ESP32**

Signed-off-by: José Simões <jose.simoes@eclo.solutions>
  • Loading branch information
josesimoes committed Dec 21, 2018
1 parent a9ad279 commit 1586348
Show file tree
Hide file tree
Showing 30 changed files with 444 additions and 248 deletions.
1 change: 0 additions & 1 deletion CMake/Modules/FindNF_Networking.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ set(NF_Networking_Security_SRCS
ssl.cpp
ssl_accept_internal.cpp
ssl_add_cert_auth_internal.cpp
ssl_clear_cert_auth_internal.cpp
ssl_closesocket_internal.cpp
ssl_connect_internal.cpp
ssl_exit_context_internal.cpp
Expand Down
1 change: 1 addition & 0 deletions CMake/Modules/FindSystem.Net.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(System.Net_SRCS

# System.Net.Security
sys_net_native_System_Net_Security_SslNative.cpp
sys_net_native_System_Net_Security_CertificateManager.cpp

)

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pr:
branches:
include:
- master
- develop
- develop/*
- release/*
autoCancel: true

Expand Down
28 changes: 26 additions & 2 deletions src/CLR/Debugger/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -853,9 +853,11 @@ bool CLR_DBG_Debugger::Monitor_QueryConfiguration( WP_Message* message)

Monitor_QueryConfiguration_Command *cmd = (Monitor_QueryConfiguration_Command*)message->m_payload;
int size = 0;
int sizeOfBlock = 0;

HAL_Configuration_NetworkInterface* configNetworkInterface;
HAL_Configuration_Wireless80211* configWireless80211NetworkInterface;
HAL_Configuration_X509CaRootBundle* x509Certificate;

switch((DeviceConfigurationOption)cmd->Configuration)
{
Expand Down Expand Up @@ -886,7 +888,28 @@ bool CLR_DBG_Debugger::Monitor_QueryConfiguration( WP_Message* message)
platform_free(configWireless80211NetworkInterface);
}
break;


case DeviceConfigurationOption_X509CaRootBundle:

if(g_TargetConfiguration.CertificateStore->Count > 0)
{
// because X509 certificate has a variable length need to compute the block size in two steps
sizeOfBlock = offsetof(HAL_Configuration_X509CaRootBundle, Certificate);
sizeOfBlock += g_TargetConfiguration.CertificateStore->Certificates[cmd->BlockIndex]->CertificateSize;
}

x509Certificate = (HAL_Configuration_X509CaRootBundle*)platform_malloc(sizeOfBlock);

if(ConfigurationManager_GetConfigurationBlock(x509Certificate, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex) == true)
{
size = sizeOfBlock;
success = true;

WP_ReplyToCommand( message, success, false, (uint8_t*)x509Certificate, size );
platform_free(x509Certificate);
}
break;

case DeviceConfigurationOption_WirelessNetworkAP:
// TODO missing implementation for now
break;
Expand Down Expand Up @@ -925,8 +948,9 @@ bool CLR_DBG_Debugger::Monitor_UpdateConfiguration(WP_Message* message)
{
case DeviceConfigurationOption_Network:
case DeviceConfigurationOption_Wireless80211Network:
case DeviceConfigurationOption_X509CaRootBundle:
case DeviceConfigurationOption_All:
if(ConfigurationManager_StoreConfigurationBlock(cmd->Data, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex, cmd->Length) == true)
if(ConfigurationManager_StoreConfigurationBlock(cmd->Data, (DeviceConfigurationOption)cmd->Configuration, cmd->BlockIndex, cmd->Length, cmd->Offset) == true)
{
cmdReply.ErrorCode = 0;
success = true;
Expand Down
1 change: 1 addition & 0 deletions src/CLR/Include/WireProtocol_MonitorCommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ typedef struct Monitor_UpdateConfiguration_Command
uint32_t Configuration;
uint32_t BlockIndex;
uint32_t Length;
uint32_t Offset;
uint8_t Data[1];

}Monitor_UpdateConfiguration_Command;
Expand Down
9 changes: 5 additions & 4 deletions src/DeviceInterfaces/System.Net/sys_net_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterfaceCount___STATIC__I4,
Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::GetNetworkInterface___STATIC__SystemNetNetworkInformationNetworkInterface__U4,
Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface::IPAddressFromString___STATIC__U4__STRING,
NULL,
NULL,
Library_sys_net_native_System_Net_Security_CertificateManager::AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1,
Library_sys_net_native_System_Net_Security_SslNative::SecureServerInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate,
Library_sys_net_native_System_Net_Security_SslNative::SecureClientInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate,
Library_sys_net_native_System_Net_Security_SslNative::UpdateCertificates___STATIC__VOID__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SZARRAY_SystemSecurityCryptographyX509CertificatesX509Certificate,
Library_sys_net_native_System_Net_Security_SslNative::SecureAccept___STATIC__VOID__I4__OBJECT,
Library_sys_net_native_System_Net_Security_SslNative::SecureConnect___STATIC__VOID__I4__STRING__OBJECT,
Library_sys_net_native_System_Net_Security_SslNative::SecureRead___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4,
Expand Down Expand Up @@ -156,7 +158,6 @@ static const CLR_RT_MethodHandler method_lookup[] =
NULL,
NULL,
NULL,
NULL,
Library_sys_net_native_System_Net_Sockets_NativeSocket::socket___STATIC__I4__I4__I4__I4,
Library_sys_net_native_System_Net_Sockets_NativeSocket::bind___STATIC__VOID__OBJECT__SZARRAY_U1,
Library_sys_net_native_System_Net_Sockets_NativeSocket::connect___STATIC__VOID__OBJECT__SZARRAY_U1__BOOLEAN,
Expand Down Expand Up @@ -234,7 +235,7 @@ static const CLR_RT_MethodHandler method_lookup[] =
const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Net =
{
"System.Net",
0xFD8EBD9C,
0x001C1FB9,
method_lookup,
{ 1, 0, 2, 2 }
{ 1, 0, 3, 0 }
};
9 changes: 8 additions & 1 deletion src/DeviceInterfaces/System.Net/sys_net_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,18 @@ struct Library_sys_net_native_System_Net_NetworkInformation_NetworkInterface

};

struct Library_sys_net_native_System_Net_Security_CertificateManager
{
NANOCLR_NATIVE_DECLARE(AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1);

//--//

};

struct Library_sys_net_native_System_Net_Security_SslNative
{
NANOCLR_NATIVE_DECLARE(SecureServerInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate);
NANOCLR_NATIVE_DECLARE(SecureClientInit___STATIC__I4__I4__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SystemSecurityCryptographyX509CertificatesX509Certificate);
NANOCLR_NATIVE_DECLARE(UpdateCertificates___STATIC__VOID__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SZARRAY_SystemSecurityCryptographyX509CertificatesX509Certificate);
NANOCLR_NATIVE_DECLARE(SecureAccept___STATIC__VOID__I4__OBJECT);
NANOCLR_NATIVE_DECLARE(SecureConnect___STATIC__VOID__I4__STRING__OBJECT);
NANOCLR_NATIVE_DECLARE(SecureRead___STATIC__I4__OBJECT__SZARRAY_U1__I4__I4__I4);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Copyright (c) 2018 The nanoFramework project contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
//

#include "sys_net_native.h"

HRESULT Library_sys_net_native_System_Net_Security_CertificateManager::AddCaCertificateBundle___STATIC__BOOLEAN__SZARRAY_U1( CLR_RT_StackFrame& stack )
{
NATIVE_PROFILE_CLR_NETWORK();
NANOCLR_HEADER();

CLR_RT_HeapBlock_Array* arrayCA = stack.Arg0().DereferenceArray();

CLR_UINT8* certificateBinary;
uint32_t certificateSize;

// we only have one CA root bundle, so this is fixed to 0
uint32_t configIndex = 0;

// check for empty array
FAULT_ON_NULL(arrayCA);

certificateSize = (int)arrayCA->m_numOfElements;

// get a pointer to the the binary data for the certificate
certificateBinary = arrayCA->GetFirstElement();

if(g_TargetConfiguration.CertificateStore->Count == 0)
{
// not found, add the certificate bundle
if(ConfigurationManager_StoreConfigurationBlock(certificateBinary, DeviceConfigurationOption_X509CaRootBundle, configIndex, certificateSize, 0) != TRUE)
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}
}
else
{
// update the configuration block
if(ConfigurationManager_UpdateConfigurationBlock(certificateBinary, DeviceConfigurationOption_X509CaRootBundle, configIndex) != TRUE)
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}
}

// reach here, we should be OK
stack.SetResult_Boolean(TRUE);

NANOCLR_NOCLEANUP();
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,53 +108,6 @@ HRESULT Library_sys_net_native_System_Net_Security_SslNative::SecureClientInit__
return InitHelper( stack, false );
}

HRESULT Library_sys_net_native_System_Net_Security_SslNative::UpdateCertificates___STATIC__VOID__I4__SystemSecurityCryptographyX509CertificatesX509Certificate__SZARRAY_SystemSecurityCryptographyX509CertificatesX509Certificate( CLR_RT_StackFrame& stack )
{
NATIVE_PROFILE_CLR_NETWORK();
NANOCLR_HEADER();

CLR_INT32 sslContext = stack.Arg0().NumericByRef().s4;
CLR_RT_HeapBlock* hbCert = stack.Arg1().Dereference();
CLR_RT_HeapBlock_Array* arrCA = stack.Arg2().DereferenceArray();
CLR_RT_HeapBlock_Array* arrCert;
CLR_UINT8* sslCert;
int i;
CLR_RT_HeapBlock* hbPwd;
const char * szPwd;

FAULT_ON_NULL(hbCert);
FAULT_ON_NULL(arrCA);

arrCert = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___certificate ].DereferenceArray(); FAULT_ON_NULL(arrCert);

sslCert = arrCert->GetFirstElement();

hbPwd = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___password ].Dereference(); FAULT_ON_NULL(hbPwd);

szPwd = hbPwd->StringText();

SSL_ClearCertificateAuthority( sslContext );

if(!SSL_AddCertificateAuthority( sslContext, (const char*)sslCert, arrCert->m_numOfElements, szPwd )) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);

for(i=0; i<(int)arrCA->m_numOfElements; i++)
{
hbCert = (CLR_RT_HeapBlock*)arrCA->GetElement( i ); FAULT_ON_NULL(arrCert);

arrCert = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___certificate ].DereferenceArray();

sslCert = arrCert->GetFirstElement();

hbPwd = hbCert[ Library_sys_net_native_System_Security_Cryptography_X509Certificates_X509Certificate::FIELD___password ].Dereference();

szPwd = hbPwd->StringText();

if(!SSL_AddCertificateAuthority( sslContext, (const char*)sslCert, arrCert->m_numOfElements, szPwd )) NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}

NANOCLR_NOCLEANUP();
}

//
// Server - socket connected now accept connection by doing the server SSL handshake
//
Expand Down
21 changes: 20 additions & 1 deletion src/HAL/Include/nanoHAL_ConfigurationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ typedef enum DeviceConfigurationOption
// Wireless Network as AP configuration block
DeviceConfigurationOption_WirelessNetworkAP = 3,

// X509 CA Root Certificates bundle block
DeviceConfigurationOption_X509CaRootBundle = 4,

// All configuration blocks
DeviceConfigurationOption_All = 255,

Expand Down Expand Up @@ -58,12 +61,25 @@ typedef struct HAL_CONFIGURATION_NETWORK_WIRELESS80211

} HAL_CONFIGURATION_NETWORK_WIRELESS80211;

// certificate store struct
// declared with a flexible array member to allow N config blocks totally independent of compilation
typedef struct HAL_CONFIGURATION_X509_CERTIFICATE
{
// count of the configs elements
uint8_t Count;

// pointer to the certificates
HAL_Configuration_X509CaRootBundle* Certificates[];

} HAL_CONFIGURATION_X509_CERTIFICATE;

// target configuration storage struct
// the memory allocation for these will have to be done as required according to the number and type of blocks found in memory
typedef struct HAL_TARGET_CONFIGURATION
{
HAL_CONFIGURATION_NETWORK* NetworkInterfaceConfigs;
HAL_CONFIGURATION_NETWORK_WIRELESS80211* Wireless80211Configs;
HAL_CONFIGURATION_X509_CERTIFICATE* CertificateStore;

} HAL_TARGET_CONFIGURATION;

Expand All @@ -81,7 +97,7 @@ bool ConfigurationManager_GetConfigurationBlock(void* configurationBlock, Device

// StoreConfigurationBlock() is defined in targetHAL_ConfigurationManager.cpp at target level because the target
// needs to be free to implement the storage of the configuration block as they see fit
bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize);
bool ConfigurationManager_StoreConfigurationBlock(void* configurationBlock, DeviceConfigurationOption configuration, uint32_t configurationIndex, uint32_t blockSize, uint32_t offset);

// UpdateConfigurationBlock() is defined in targetHAL_ConfigurationManager.cpp at target level because the target
// needs to be free to implement the storage of the configuration block as they see fit
Expand All @@ -103,6 +119,9 @@ void* ConfigurationManager_FindNetworkConfigurationBlocks(uint32_t startAddress,
// function that sweeps a memory region searching for wireless network configuration blocks
void* ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks(uint32_t startAddress, uint32_t endAddress);

// function that sweeps a memory region searching for X509 certificates configuration blocks
void* ConfigurationManager_FindX509CertificateConfigurationBlocks(uint32_t startAddress, uint32_t endAddress);

// gets the HAL_Configuration_Wireless80211 configuration block that has the specified Id, if that exists
// defined as weak needs to be free to implement the storage of the configuration block as they see fit
HAL_Configuration_Wireless80211* ConfigurationManager_GetWirelessConfigurationFromId(uint32_t configurationId);
Expand Down
17 changes: 17 additions & 0 deletions src/HAL/Include/nanoHAL_Network.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ static const unsigned char c_MARKER_CONFIGURATION_WIRELESS80211_V1[] = "WN1";
// Wireless AP configuration block start marker
static const unsigned char c_MARKER_CONFIGURATION_WIRELESS_AP_V1[] = "AP1";

// X509 certificate configuration block start marker
static const unsigned char c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1[] = "XB1";

////////////////////////////////////////////////////////////////////////////////////////////////////
// !!! KEEP IN SYNC WITH System.Net.NetworkInformation.NetworkInterfaceType (in managed code) !!! //
////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -206,6 +209,20 @@ typedef struct __nfpack HAL_Configuration_Wireless80211 {

} HAL_Configuration_Wireless80211;

typedef struct __nfpack HAL_Configuration_X509CaRootBundle {

// this is the marker placeholder for this configuration block
uint8_t Marker[4];

// Size of the X509 CA Root certificate bundle
uint32_t CertificateSize;

// X509 CA Root certificate bundle
uint8_t Certificate[1];

} HAL_Configuration_X509CaRootBundle;


void nanoHAL_Network_Initialize();
void sys_signal_sock_event();

Expand Down
47 changes: 47 additions & 0 deletions src/HAL/nanoHAL_ConfigurationManager.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <string.h>
#include <nanoHAL_v2.h>
#include <nanoHAL_Network.h>

uint32_t FindNextBlock(uint32_t startAddress, uint32_t endAddress, const unsigned char* marker)
{
Expand Down Expand Up @@ -105,6 +106,52 @@ __nfweak void* ConfigurationManager_FindNetworkWireless80211ConfigurationBlocks(
return networkWirelessConfigs;
}

__nfweak void* ConfigurationManager_FindX509CertificateConfigurationBlocks(uint32_t startAddress, uint32_t endAddress)
{
uint32_t nextBlock = startAddress;
uint32_t allocationSize = 0;

// first pass: find out how many blocks of this type we have
// because these blocks have an unknow size, need to call this without a fixed size
uint32_t blockCount = GetBlockCount(startAddress, endAddress, 1, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1);

// start computing allocation size, first part is the struct initial fields
allocationSize = offsetof(HAL_CONFIGURATION_X509_CERTIFICATE, Certificates);

// second pass: find out the size of each X509 certificate (because they can have different sizes and we need this to allocate memory for the struct)
if(blockCount > 0)
{
for(uint32_t i = 0; i < blockCount; i++)
{
nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1);

// header
allocationSize += offsetof(HAL_Configuration_X509CaRootBundle, Certificate);

// certificate
allocationSize += ((HAL_Configuration_X509CaRootBundle*)nextBlock)->CertificateSize;
}
}

// allocate config struct
HAL_CONFIGURATION_X509_CERTIFICATE *certificateStore = (HAL_CONFIGURATION_X509_CERTIFICATE *)platform_malloc(allocationSize);

// set collection count
certificateStore->Count = blockCount;

if(blockCount > 0)
{
// second pass: get address of each config block
for(uint32_t i = 0; i < blockCount; i++)
{
nextBlock = FindNextBlock(nextBlock, endAddress, c_MARKER_CONFIGURATION_X509CAROOTBUNDLE_V1);
certificateStore->Certificates[i] = (HAL_Configuration_X509CaRootBundle*)nextBlock;
}
}

return certificateStore;
}

__nfweak HAL_Configuration_Wireless80211* ConfigurationManager_GetWirelessConfigurationFromId(uint32_t configurationId)
{
for(int i = 0; i < g_TargetConfiguration.Wireless80211Configs->Count; i++)
Expand Down
Loading

0 comments on commit 1586348

Please sign in to comment.