Security and Safety - JawaharT/Best-Practices-On-Azure-Sphere GitHub Wiki
This section will show what can be done to keep your devices as secure as possible on top of the security benefits provided out of the box by the Azure Sphere platform. This is important to keep in mind because once your system is built, the question of keeping the product safe from a physical standpoint remains. These guidelines should be able to keep your devices as safe as possible from all aspects (software and hardware).
The Azure Sphere platform has built-in layered security. These are the principles it adheres to:
- Hardware-based root of trust to prevent forgery or spoofing
- Renewable Security
- Dynamic Compartments to limit the spread of errors and hardware issues as well as encryption of data
- Defence in Depth to analyse that each OS layer before it is secured to continue
- Small Trusted Computing Base where only Microsoft approved systems such as the Security Monitor and the SOC’s Pluton runtime and subsystem are trusted for use
- Password-less Authentication is only achieved through verified certificates for device communication
- Error Reporting, to communicate as early as possible before a potential problem may occur
You can read more about these principles here: Seven Security Principles for Highly Secured Devices
The Azure Sphere platform has many features to protect devices connected to a Tenant and the cloud. These include:
- Containerised software, all programs developed is run on a Docker Container once uploaded onto a board which will help minimise dependencies as part of Dynamic Compartments
- Secure Boot onto the OS of the board to view outputs or the debug console
- Frequent Azure Sphere OS security updates by Microsoft as part of the Renewable Security aspect
- Flash (storage) Space is locked but still mutable for the application to run once the ‘cloud-test’ command is enabled which will ensure the board cannot be overwritten with another program
- Hardware Firewalls to keep individual components safe from attacks as part of Dynamic Compartments
There are multiple ways to secure IoT devices here are some:
- Add a return status to all functions because C does not have built-in exception handling, it is ideal to create your own errors for easier debugging purposes
- use safe C runtime functions such as strncpy (as seen in a previous example)
- Validate data inputs (values and sizes)
- Buffer Validation
- Allocate all resources that are going to be used at the start such as hardware and memory (as mentioned in a previous section)
- Certificates to validate other systems connected
Fuzz testing can also be performed which is a technique to provide invalid, random, or unexpected data as inputs. The program is run with these inputs and is monitored for exceptions, crashes, and memory leaks. This can then be used to improve the program for various scenarios that may have no been foreseen previously during development. An example is similar to the one below but is automated.
It is important in C to distinguish between data types and bounds checking as seen below especially when using printf function to prevent buffer overflows (keep within the buffer space). The below example presents the ideal data input validation scheme to check if a string contains a valid four-digit code. It incorporates the use of the best practices described. The current_code variable represents a user input from keypad.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int isStrPresent(const char *code){
int count = 0, character;
for(character = 0; character < strlen(code); character++){
if(isdigit(code[character])){
count++;
}
}
if(count == strlen(code)){
return 0;
}else{
return 1;
}
}
int main(void) {
// Will only take first 4 characters in a string
char current_code[5] = "1234";
if(isStrPresent(current_code) == 0){
if (strlen(current_code) == 4){
int integer_code = atoi(current_code);
// Length has to be 4
if(integer_code >= 1000 && integer_code <= 9999){
printf("A valid 4 digit code present.\n");
}
}else{
printf("Try again, a 4 digit code required.\n");
}
}else{
printf("Try again, only enter digits.\n");
}
}
Output for ideal input:
A valid 4 digit code present.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int isStrPresent(const char *code){
int count = 0, character;
for(character = 0; character < strlen(code); character++){
if(isdigit(code[character])){
count++;
}
}
if(count == strlen(code)){
return 0;
}else{
return 1;
}
}
int main(void) {
// Will only take first 4 characters in a string
char current_code[5] = "1234dsf";
if(isStrPresent(current_code) == 0){
if (strlen(current_code) == 4){
int integer_code = atoi(current_code);
// Length has to be 4
if(integer_code >= 1000 && integer_code <= 9999){
printf("A valid 4 digit code present.\n");
}
}else{
printf("Try again, a 4 digit code required.\n");
}
}else{
printf("Try again, only enter digits.\n");
}
}
Output for not ideal input from keypad (too long/incorrect characters):
Try again, only enter digits.
This section will have provided an overview of how you could keep the physical device as well as all the internal layers as secure as possible. The security ranges from the SOC architecture to the physical circuit board level including communication to the cloud via Azure IoT Hub. At a software level, these include data input validation before processing and containerising (completed automatically by Azure Sphere if development mode enabled) to say the least.