Bluetooth provides secure connections through pairing and bonding but there are many reasons why the Bluetooth features may not be desirable for your application. For instance, the stack limits you in the number of bonded devices that can be supported. If your design requires you to support more devices (aka clients) then application layer security may be your only choice.
Discussion
ARM specifies a standard implementation for AES encryption called mbedtls. Using mbedtls ensures that your application’s use of the crypto accelerator does not conflict with the stack. This article discusses an implementation of AES128-CBC but can easily be extended to any variation of AES supported by mbedtls. This example uses keys and initialization values of zero, a practical application should use non-zero values for more secure communication. Both the server and client projects in this example are built for the GCC compiler. Two wireless starter kits (WSTK) with radio boards will be required to run this example as described.
Implementation
The example discussed here requires the use of a custom service with two characteristics : one for incoming data and the other for outgoing data. Each data characteristic is 16 bytes since AES128 used here. The incoming data is called cipher_text_in and the outgoing data is called cipher_text_out. Both characteristics have the user type since the user application needs to handle reading and writing.
AES128-CBC requires a 16 byte key, a 16 byte block of data to operate on and a 16 byte initialization vector, both the key and initialization vectors (IV) are set to zero in this example. One IV is required for each characteristic in order for the client and server to remain in sync.
Server
The first step is to initialize the mbedtls module with a call to mbedtls_aes_init().This function requires a pointer to a mbedtls_aes_context struct, a struct of this type is declared extern just main().
Once the initialization is done it is safe to either encrypt or decrypt a block of data. Either operation can be done with a call to the helper function handle_encryption_cbc().This function takes the following parameters : a pointer to the data to be encrypted or decrypted, a pointer to the key, a pointer to the iv and a flag to indicate whether the operation is to encrypt or decrypt.
When the server application receives a request from a remote device to read the cipher_text_out characteristic, the data is encrypted with a call to ciphertext = handle_encryption_cbc(plaintext,key,iv,MBEDTLS_AES_ENCRYPT);
and the resulting encrypted data is sent to the remote system by making a call to gatt_server_send_user_read_response().
Similarly, when a request is received to write the cipher_text_in characteristic, the incoming data is decrypted with a call to handle_encryption_cbc() and the data is printed out.
Client
For demonstration purposes, it is simpler to write a client to run on an EFR32 platform rather than a mobile device. So a sample client is provided.
Upon startup, the client begins listening for a server that advertises our custom service with the UUID 8dcd0dfe-0faf-499a-9993-4010c20db5da. When a device advertising this service is found, a connection is opened. Once the connection is established, the client performs discovery to get the necessary service and characteristic handles. The client uses a state variable to keep track of its connection and discovery state. This allows the application to perform reads and writes of the secure data characteristics using the gatt_procedure_completed event. This ensures that any previous GATT procedures have completed before attempting another.
The client uses an identical setup of mbedtls and helper function. As with the server, a separate IV is used for each characteristic. Note that if either device resets, it’s IV will be reset to zero and it may become out of sync with the device it connects to. To solve this problem, both IVs are reset to zero as soon as the connection is closed.
Running the Example
The applications are built for an EFR32MG1 but will run on any of the EFR32xG1 SoC or module boards.
Unzip “application security client and server.zip” and import the two projects into an existing workspace in SimplicityStudio.
Build the server project found in the “application security” folder and download the binary to your target board.
Right click on the device in the devices tab and select launch console as shown.
Select the serial1 tab. Click in the textbox at the bottom of the console and hit enter to start serial communication.
Press reset on the WSTK and you’ll see the following message
Application security server example booted
Now build the client project found in the “SecurityClient” folder and download it to a second target board as you did with the server project.
Launch the console and hit the reset button as before.
The client comes up and displays the following message
Application security client example booted
The client begins scanning for devices advertising a service with a known UUID 8dcd0dfe-0faf-499a-9993-4010c20db5da. When a device advertising this service is found, it connects and displays a message such as the following
connecting to remote GATT server with address 00:0B:57:27:B1:07
Once a connection is established, the client proceeds through the discovery process to assign handles for the custom service and characteristics. Debug messages that display information about the connection state, crypto operations can enabled by uncommenting the appropriate lines of code.
As soon as the writeable characteristic is discovered, the client encrypts the message “First message” as
E66EA45987C01B9C45BABE287E61591 and sends this data to the server. When the readable characteristic is discovered, the client reads this characteristic from the server by calling gecko_cmd_gatt_read_characteristic_value(). The data is received as 55966D11134CB15DBAF7EBC39823F
and decoded as “attack!!”. Note that the encrypted values will change if sent a second time due to the chained nature of the CBC algorithm.
It is also possible to connect to the server from a mobile device using the Silabs BlueGecko app. Open the Bluetooth Browser, expand the unknown service and you’ll see there are two characteristics : one with the read and write properties and the other with only the read property. Expand the characteristic with only the read property to see the encrypted data.
Conclusion
Application layer security provides you with more flexibility than the built-in BLE security such as the ability to choose the encryption algorithm but also requires a little more work to implement.
Update: The example code has been updated to support the structure of our Bluetooth SDK v2.7. Please find the new example attached to this article in addition to the v2.4.x example
Tried to import this project in SS 4.0. On importing the project it is listed as " External Project Type ".
When building the project I get
Errors occurred during the build. Errors running builder 'CDT Builder' on project 'SecurityClient'. failed to generate linker script The system cannot find the path specified failed to generate linker script The system cannot find the path specified
0
Hi,
I just imported the projects directly from the zip and they build like a charm.
Please make sure that your studio is fully updated and that you have BLE SDK 2.4.2.
Then go to Studio IDE and select File -> Import -> General -> Existing Projects into Workspace, select the *.zip as the archive file and it should import and build fine.
Regards,
Tiago
0
Brilliant. Worked like a charm.
Sorry to be a pain, but what was wrong with the process that I followed:
The Bluetooth projects are not MCU projects as such, the correct way to import them is with "Existing projects into Workspace".
As for your second question, the needed files were just added manually so that project property is not relevant.
Regards,
Tiago
0
Hi Tiago
I am still batteling with this project. I have created an empty project and have tried to replicate the "Securityclient" project. However on build I get:
1. Description Resource Path Location Type
fatal error: cryptodrv.h: No such file or directory soc-reky-rev4 line 33, external location: C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v1.0\util\ third_party\mbedtls\sl_crypto\src\cryptodrv_internal.h C/C++ Problem
2. Description Resource Path Location Type
make: *** [mbedtls/aesdrv_blockcipher_crypto.o] Error 1 soc-reky-rev4 C/C++ Problem
3. Description Resource Path Location Type
make: *** [mbedtls/aesdrv_common_crypto.o] Error 1 soc-reky-rev4 C/C++ Problem
4. Description Resource Path Location Type
make: *** Waiting for unfinished jobs.... soc-reky-rev4 C/C++ Problem
The process of making the project was:
1. Empty SOC BLE project based on SDK 2.4.2
2. Added mbedtls folder and copied file mbedtld_config.h into folder
3. Added link files to mbedtls directoy for: aes.c, aesdrv_blockcipher_crypto.c, aesdrv_common_crypto.c, cryptodrv.c, slcl_aes.c, slcl_device.c
4. Added links to emlib folder for em_crypto.c
5. Added symbol MBEDTLS_CONFIG_FILE = "mbedtls_config.h" in project properties
6. Added include paths: ${StudioSdkPath}/util/third_party/mbedtls/include, ${StudioSdkPath}/util/third_party/mbedtls/sl_crypto/include, ${StudioSdkPath}/util/third_party/mbedtls/sl_crypto/src, ${StudioSdkPath}/util/third_party/mbedtls/include/mbedtls, /${ProjName}/mbedtls
I have checked that cryptodrv.h exists and that the header path is correct.
0
Using a hardcoded shared AES key in the server and client isn't at all a good security practice
You should recommend your users to use a standard key exchange algorithm and since you're using mbed_tls everything needed is available
0
How to use AES-CTR 256 bit key encryption? Where can I get the proper documentation regarding this?
KBA_BT_1103: Application Layer Security
Introduction
Bluetooth provides secure connections through pairing and bonding but there are many reasons why the Bluetooth features may not be desirable for your application. For instance, the stack limits you in the number of bonded devices that can be supported. If your design requires you to support more devices (aka clients) then application layer security may be your only choice.
Discussion
ARM specifies a standard implementation for AES encryption called mbedtls. Using mbedtls ensures that your application’s use of the crypto accelerator does not conflict with the stack. This article discusses an implementation of AES128-CBC but can easily be extended to any variation of AES supported by mbedtls. This example uses keys and initialization values of zero, a practical application should use non-zero values for more secure communication. Both the server and client projects in this example are built for the GCC compiler. Two wireless starter kits (WSTK) with radio boards will be required to run this example as described.
Implementation
The example discussed here requires the use of a custom service with two characteristics : one for incoming data and the other for outgoing data. Each data characteristic is 16 bytes since AES128 used here. The incoming data is called cipher_text_in and the outgoing data is called cipher_text_out. Both characteristics have the user type since the user application needs to handle reading and writing.
AES128-CBC requires a 16 byte key, a 16 byte block of data to operate on and a 16 byte initialization vector, both the key and initialization vectors (IV) are set to zero in this example. One IV is required for each characteristic in order for the client and server to remain in sync.
Server
The first step is to initialize the mbedtls module with a call to mbedtls_aes_init().This function requires a pointer to a mbedtls_aes_context struct, a struct of this type is declared extern just main().
Once the initialization is done it is safe to either encrypt or decrypt a block of data. Either operation can be done with a call to the helper function handle_encryption_cbc().This function takes the following parameters : a pointer to the data to be encrypted or decrypted, a pointer to the key, a pointer to the iv and a flag to indicate whether the operation is to encrypt or decrypt.
When the server application receives a request from a remote device to read the cipher_text_out characteristic, the data is encrypted with a call to ciphertext = handle_encryption_cbc(plaintext,key,iv,MBEDTLS_AES_ENCRYPT);
and the resulting encrypted data is sent to the remote system by making a call to gatt_server_send_user_read_response().
Similarly, when a request is received to write the cipher_text_in characteristic, the incoming data is decrypted with a call to handle_encryption_cbc() and the data is printed out.
Client
For demonstration purposes, it is simpler to write a client to run on an EFR32 platform rather than a mobile device. So a sample client is provided.
Upon startup, the client begins listening for a server that advertises our custom service with the UUID 8dcd0dfe-0faf-499a-9993-4010c20db5da. When a device advertising this service is found, a connection is opened. Once the connection is established, the client performs discovery to get the necessary service and characteristic handles. The client uses a state variable to keep track of its connection and discovery state. This allows the application to perform reads and writes of the secure data characteristics using the gatt_procedure_completed event. This ensures that any previous GATT procedures have completed before attempting another.
The client uses an identical setup of mbedtls and helper function. As with the server, a separate IV is used for each characteristic. Note that if either device resets, it’s IV will be reset to zero and it may become out of sync with the device it connects to. To solve this problem, both IVs are reset to zero as soon as the connection is closed.
Running the Example
The applications are built for an EFR32MG1 but will run on any of the EFR32xG1 SoC or module boards.
Application security server example booted
Application security client example booted
connecting to remote GATT server with address 00:0B:57:27:B1:07
E66EA45987C01B9C45BABE287E61591 and sends this data to the server. When the readable characteristic is discovered, the client reads this characteristic from the server by calling gecko_cmd_gatt_read_characteristic_value(). The data is received as 55966D11134CB15DBAF7EBC39823F
and decoded as “attack!!”. Note that the encrypted values will change if sent a second time due to the chained nature of the CBC algorithm.
Conclusion
Application layer security provides you with more flexibility than the built-in BLE security such as the ability to choose the encryption algorithm but also requires a little more work to implement.
Update: The example code has been updated to support the structure of our Bluetooth SDK v2.7. Please find the new example attached to this article in addition to the v2.4.x example
Tried to import this project in SS 4.0. On importing the project it is listed as " External Project Type ".
When building the project I get
Errors occurred during the build.
Errors running builder 'CDT Builder' on project 'SecurityClient'.
failed to generate linker script
The system cannot find the path specified
failed to generate linker script
The system cannot find the path specified
Hi,
I just imported the projects directly from the zip and they build like a charm.
Please make sure that your studio is fully updated and that you have BLE SDK 2.4.2.
Then go to Studio IDE and select File -> Import -> General -> Existing Projects into Workspace, select the *.zip as the archive file and it should import and build fine.
Regards,
Tiago
Brilliant. Worked like a charm.
Sorry to be a pain, but what was wrong with the process that I followed:
IDE->Project->Import -> MCU project-> SecurityClient.is
Also having a look at the working project I see that mbedtls module is not enabled?
Project-> properties->C/C++ Build->Project modules->3rd party?
Hi @BryPie
The Bluetooth projects are not MCU projects as such, the correct way to import them is with "Existing projects into Workspace".
As for your second question, the needed files were just added manually so that project property is not relevant.
Regards,
Tiago
I am still batteling with this project. I have created an empty project and
have tried to replicate the "Securityclient" project. However on build I
get:
1. Description Resource Path Location Type
fatal error: cryptodrv.h: No such file or directory soc-reky-rev4 line 33,
external location:
C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v1.0\util\
third_party\mbedtls\sl_crypto\src\cryptodrv_internal.h C/C++ Problem
2. Description Resource Path Location Type
make: *** [mbedtls/aesdrv_blockcipher_crypto.o] Error 1 soc-reky-rev4 C/C++
Problem
3. Description Resource Path Location Type
make: *** [mbedtls/aesdrv_common_crypto.o] Error 1 soc-reky-rev4 C/C++
Problem
4. Description Resource Path Location Type
make: *** Waiting for unfinished jobs.... soc-reky-rev4 C/C++ Problem
The process of making the project was:
1. Empty SOC BLE project based on SDK 2.4.2
2. Added mbedtls folder and copied file mbedtld_config.h into
folder
3. Added link files to mbedtls directoy for: aes.c,
aesdrv_blockcipher_crypto.c, aesdrv_common_crypto.c, cryptodrv.c,
slcl_aes.c, slcl_device.c
4. Added links to emlib folder for em_crypto.c
5. Added symbol MBEDTLS_CONFIG_FILE = "mbedtls_config.h" in
project properties
6. Added include paths:
${StudioSdkPath}/util/third_party/mbedtls/include,
${StudioSdkPath}/util/third_party/mbedtls/sl_crypto/include,
${StudioSdkPath}/util/third_party/mbedtls/sl_crypto/src,
${StudioSdkPath}/util/third_party/mbedtls/include/mbedtls,
/${ProjName}/mbedtls
I have checked that cryptodrv.h exists and that the header path is correct.
Using a hardcoded shared AES key in the server and client isn't at all a good security practice
You should recommend your users to use a standard key exchange algorithm and since you're using mbed_tls everything needed is available