1
0
mirror of https://github.com/FreeRTOS/FreeRTOS.git synced 2025-06-12 02:44:28 +08:00

Add feature to set credentials using buffer in MQTT_Mutual_Auth_wolfSSL demo ()

* Add feature to set credentials using buffer
* Change instructions for giving credential data via buffer
This commit is contained in:
TakayukiMatsuo
2021-04-22 03:09:43 +09:00
committed by GitHub
parent 9f10725bee
commit 1e2f99a11b
4 changed files with 231 additions and 94 deletions
FreeRTOS-Plus
Demo/coreMQTT_Windows_Simulator/MQTT_Mutual_Auth_wolfSSL
Source/Application-Protocols/network_transport/freertos_plus_tcp/using_wolfSSL

@ -434,19 +434,26 @@ static void prvMQTTDemoTask( void * pvParameters )
}
}
/*-----------------------------------------------------------*/
static void prvTLSConnect( NetworkCredentials_t * pxNetworkCredentials,
NetworkContext_t * pxNetworkContext )
{
BaseType_t xNetworkStatus;
/* Set the credentials for establishing a TLS connection. */
pxNetworkCredentials->pRootCa = ( const unsigned char * ) democonfigROOT_CA_PEM;
pxNetworkCredentials->rootCaSize = sizeof( democonfigROOT_CA_PEM );
pxNetworkCredentials->pClientCert = ( const unsigned char * ) democonfigCLIENT_CERTIFICATE_PEM;
pxNetworkCredentials->clientCertSize = sizeof( democonfigCLIENT_CERTIFICATE_PEM );
pxNetworkCredentials->pPrivateKey = ( const unsigned char * ) democonfigCLIENT_PRIVATE_KEY_PEM;
#if defined( democonfigCREDENTIALS_IN_BUFFER )
pxNetworkCredentials->rootCaSize = strlen( democonfigROOT_CA_PEM );
pxNetworkCredentials->clientCertSize = strlen( democonfigCLIENT_CERTIFICATE_PEM );
pxNetworkCredentials->privateKeySize = strlen( democonfigCLIENT_PRIVATE_KEY_PEM );
#else
pxNetworkCredentials->rootCaSize = sizeof( democonfigROOT_CA_PEM );
pxNetworkCredentials->clientCertSize = sizeof( democonfigCLIENT_CERTIFICATE_PEM );
pxNetworkCredentials->privateKeySize = sizeof( democonfigCLIENT_PRIVATE_KEY_PEM );
#endif
/* Attempt to create a mutually authenticated TLS connection. */
xNetworkStatus = TLS_FreeRTOS_Connect( pxNetworkContext,

@ -10,18 +10,86 @@ By double-clicking the solution file named "**mqtt_mutual_auth_demo_wolfSSL.sln*
All required settings for wolfSSL have been set in the user_settings.h header file included in the RTOSDemo folder in the solution explorer pane. For this demo to work, you need to set the following information:
1. choose interface to use
2. set MQTT broker endpoint URL
2. set root CA certificate file(.pem) path
3. set private key file(.pem) path
1. set broker endpoint
2. set root CA certificate
3. set client certificate
4. set private key
5. choose interface to use
If even one of the above 1 to 4 is not set, an error will occur at build time. You should open **demo_config.h** to set them.
<br>
# Set Broker endpoint
A broker endpoint is a url that represents where MQTT subscribers and publishers access. In case your device is going to access AWS IoT device data endpoints, the endpoint would be the following format: ***account-specific-prefix*.iot.*aws-region*. amazonaws.com**.
To set broker endpoint, find the statement '**#define democonfigMQTT_BROKER_ENDPOINT "...insert here...**' in demo_config.h and activate it by copy & paste to the outside of the commented part. Replace "...insert here..." with your broker endpoint url.
```
#define democonfigMQTT_BROKER_ENDPOINT "a****.iot.us-***.amazonaws.com"
```
You may find "democonfigMQTT_BROKER_PORT" just below of the democonfigMQTT_BROKER_ENDPOINT macro. If your MQTT broker port is "8883", no need to specifiy that value here, since the value is defined in MutualAuthMQTTExample.c by default.
<br>
# Set Credentials
Since this demo handles mutual authentication, you need to provide rootCA certificate, client certificate and client private key. Those credentials should be set by way of following macros in demo_config.h:
1. **democonfigROOT_CA_PEM**
2. **democonfigCLIENT_CERTIFICATE_PEM**
3. **democonfigCLIENT_PRIVATE_KEY_PEM**
For setting those credentials, you have a option to specify the source of them, using file or using buffer. If you want provide credentials using buffer,
activate **democonfigCREDENTIALS_IN_BUFFER** macro. Otherwise, let the macro commented out.
```
#define democonfigCREDENTIALS_IN_BUFFER
```
<br>
## Setting credentials using file
<br>
By default, above **democonfigCREDENTIALS_IN_BUFFER** macro definition is commented out, therefore each credential should be provided by PEM encoded file. In this case, each macro definition looks like:
```
#define democonfigROOT_CA_PEM "rootCA-PEM-encoded-file-path"
```
Activate two other macro definitions and set a file path for each.
<br>
## Setting credential using buffer
<br>
First of all, activate **democonfigCREDENTIALS_IN_BUFFER** macro.
```
#define democonfigCREDENTIALS_IN_BUFFER
```
Second, activate following three macros:
```
#define democonfigROOT_CA_PEM "...insert here..."
#define democonfigCLIENT_CERTIFICATE_PEM "...insert here..."
#define democonfigCLIENT_PRIVATE_KEY_PEM "...insert here..."
```
The "...insert here..." portion of each macro should be replaced with corrensponding credential file content data.
For exsample, democonfigROOT_CA_PEM macro would be:
```
#define democonfigROOT_CA_PEM \
"-----BEGIN CERTIFICATE-----\n"
"MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n" \
......
"-----END CERTIFICATE-----\n"
```
If you completes above settings, re-build demo to continue with the final setup.
# Choose an interface to use
You should choose an interface to use to configure the demo. However you may not know how to choose it. The demo will give you good guidance. Follow the steps below.
1. Build the RTOSDemo project
2. Run the RTOSDemo.exe
At this point, assume that you have completed all the necessary settings other than this interface settings and the demo is runnable. Remember you should choose an interface to use to configure the demo. However you may not know how to choose it. The demo will give you good guidance. Run the demo.
A console that pops up appears with output similar to the following:
```
@ -68,27 +136,9 @@ vDHCPProcess: offer 192.168.1.6
6 600 [MQTTDemo] [INFO] [MQTT-wolfSSL] [prvMQTTDemoTask:356] Creating a TLS connection to ...insert here...:8883.
vAssertCalled( ***\FreeRTOS\FreeRTOS-Plus\Demo\coreMQTT_Windows_Simulator\MQTT_Mutual_Auth_wolfSSL\DemoTasks\MutualAuthMQTTExample.c, 457
```
<br>
The demo stops by assertion. The log saying "Creating a TLS connection to **...insert here...**:8883" has a hint.
<br>
# Set Credentials
Please remember you need to provide the remaining information to complete the demo configuration. This time, you should open **demo_config.h** and find following defininitions:
- **democonfigMQTT_BROKER_ENDPOINT**
- **democonfigROOT_CA_PEM**
- **democonfigCLIENT_CERTIFICATE_PEM**
- **democonfigCLIENT_PRIVATE_KEY_PEM**
All have **"...insert here..."** as their defined value. This is the casuse of the assertion that stopped the demo. In the file, "...insert here..." is used as a placeholder. Therefore, you need to specify the correct value for each. Immediately above them, there is information on how and what to set for each definitions.
Please refer the [coreMQTT Demo(Mutual Authentication)](https://www.freertos.org/mqtt/mutual-authentication-mqtt-example.html) page to get more information.
If you completes above settings, re-build demo and run it.
# Demo output
Below is the output digest when a Aws MQTT IoT endpoint and appropriate credentials are set. You can find "**Hello World!**" message was published and received as a topic repeatedly.

@ -104,6 +104,25 @@ extern void vLoggingPrintf(const char* pcFormatString,
*/
/**
* @brief Credentials source.
*
* Users can choose either a file or a buffer to pass to the TLS component
* as a source of credentials such as certificates and private keys. By default,
* following macros expect to have file paths:
* - democonfigROOT_CA_PEM
* - democonfigCLIENT_CERTIFICATE_PEM
* - democonfigCLIENT_PRIVATE_KEY_PEM
* If users want to pass those credentials not via files but buffers,
* enable democonfigCREDENTIALS_IN_BUFFER macro below and set buffer
* containing the credential data to each of the above three macros.
*
* @note This macro affects for all said three macros, do not mix file path
* and buffer to those macros.
*
* #define democonfigCREDENTIALS_IN_BUFFER
*/
/**
* @brief Server's root CA certificate.
*
* For AWS IoT MQTT broker, this certificate is used to identify the AWS IoT
@ -113,8 +132,8 @@ extern void vLoggingPrintf(const char* pcFormatString,
*
*
* @note This certificate should be PEM-encoded.
* @note Define the path to the certificate, do not copy and paste the certificate
* contents to this macro.
* @note If democonfigCREDENTIALS_IN_BUFFER is defined, define the certificate data.
* Otherwise, define the path to the certificate.
* @warning If wolfSSL cannot verify the peer when connecting to AWS IoT, try
* using the root CA of Starfield Services found at
* https://www.amazontrust.com/repository/SFSRootCAG2.pem.
@ -132,8 +151,8 @@ extern void vLoggingPrintf(const char* pcFormatString,
* https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html
*
* @note This certificate should be PEM-encoded.
* @note Define the path to the certificate, do not copy and paste the certificate
* contents to this macro.
* @note If democonfigCREDENTIALS_IN_BUFFER is defined, define the certificate data.
* Otherwise, define the path to the certificate.
*
* #define democonfigCLIENT_CERTIFICATE_PEM "...insert here..."
*/
@ -146,8 +165,8 @@ extern void vLoggingPrintf(const char* pcFormatString,
* https://docs.aws.amazon.com/iot/latest/developerguide/client-authentication.html
*
* @note This private key should be PEM-encoded.
* @note define the path to the certificate, do not copy and paste the certificate
* contents to this macro.
* @note If democonfigCREDENTIALS_IN_BUFFER is defined, define the key data.
* Otherwise, define the path to the key file.
*
* #define democonfigCLIENT_PRIVATE_KEY_PEM "...insert here..."
*/

@ -118,6 +118,16 @@ static int wolfSSL_IOSendGlue( WOLFSSL * ssl,
int sz,
void * context );
/*
* @brief Load credentials from file/buffer
*
* @param[in] pNetCtx NetworkContext_t
* @param[in] pNetCred NetworkCredentials_t
*
* @return #TLS_TRANSPORT_SUCCESS, #TLS_TRANSPORT_INVALID_CREDENTIALS.
*/
static TlsTransportStatus_t loadCredentials( NetworkContext_t * pNetCtx,
const NetworkCredentials_t * pNetCred );
/*-----------------------------------------------------------*/
static int wolfSSL_IORecvGlue( WOLFSSL * ssl,
@ -189,6 +199,84 @@ static TlsTransportStatus_t initTLS( void )
return TLS_TRANSPORT_SUCCESS;
}
/*-----------------------------------------------------------*/
static TlsTransportStatus_t loadCredentials( NetworkContext_t * pNetCtx,
const NetworkCredentials_t * pNetCred )
{
TlsTransportStatus_t returnStatus = TLS_TRANSPORT_SUCCESS;
configASSERT( pNetCtx != NULL );
configASSERT( pNetCred != NULL );
#if defined( democonfigCREDENTIALS_IN_BUFFER )
if( wolfSSL_CTX_load_verify_buffer( pNetCtx->sslContext.ctx,
( const byte * ) ( pNetCred->pRootCa ), ( long ) ( pNetCred->rootCaSize ),
SSL_FILETYPE_PEM ) == SSL_SUCCESS )
{
if( wolfSSL_CTX_use_certificate_buffer( pNetCtx->sslContext.ctx,
( const byte * ) ( pNetCred->pClientCert ), ( long ) ( pNetCred->clientCertSize ),
SSL_FILETYPE_PEM ) == SSL_SUCCESS )
{
if( wolfSSL_CTX_use_PrivateKey_buffer( pNetCtx->sslContext.ctx,
( const byte * ) ( pNetCred->pPrivateKey ), ( long ) ( pNetCred->privateKeySize ),
SSL_FILETYPE_PEM ) == SSL_SUCCESS )
{
returnStatus = TLS_TRANSPORT_SUCCESS;
}
else
{
LogError( ( "Failed to load client-private-key from buffer" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
LogError( ( "Failed to load client-certificate from buffer" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
LogError( ( "Failed to load ca-certificate from buffer" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
return returnStatus;
#else /* if defined( democonfigCREDENTIALS_IN_BUFFER ) */
if( wolfSSL_CTX_load_verify_locations( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pRootCa ), NULL ) == SSL_SUCCESS )
{
if( wolfSSL_CTX_use_certificate_file( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pClientCert ), SSL_FILETYPE_PEM )
== SSL_SUCCESS )
{
if( wolfSSL_CTX_use_PrivateKey_file( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pPrivateKey ), SSL_FILETYPE_PEM )
== SSL_SUCCESS )
{
returnStatus = TLS_TRANSPORT_SUCCESS;
}
else
{
LogError( ( "Failed to load client-private-key file" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
LogError( ( "Failed to load client-certificate file" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
LogError( ( "Failed to load ca-certificate file" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
return returnStatus;
#endif /* if defined( democonfigCREDENTIALS_IN_BUFFER ) */
}
/*-----------------------------------------------------------*/
static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetCtx,
@ -213,17 +301,8 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetCtx,
if( pNetCtx->sslContext.ctx != NULL )
{
/* attempt to load ca cert file, client cert file and client private key file */
if( wolfSSL_CTX_load_verify_locations( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pRootCa ), NULL ) == SSL_SUCCESS )
{
if( wolfSSL_CTX_use_certificate_file( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pClientCert ), SSL_FILETYPE_PEM )
== SSL_SUCCESS )
{
if( wolfSSL_CTX_use_PrivateKey_file( pNetCtx->sslContext.ctx,
( const char * ) ( pNetCred->pPrivateKey ), SSL_FILETYPE_PEM )
== SSL_SUCCESS )
/* load credentials from file */
if( loadCredentials( pNetCtx, pNetCred ) == TLS_TRANSPORT_SUCCESS )
{
/* create a ssl object */
pNetCtx->sslContext.ssl =
@ -275,25 +354,7 @@ static TlsTransportStatus_t tlsSetup( NetworkContext_t * pNetCtx,
wolfSSL_CTX_free( pNetCtx->sslContext.ctx );
pNetCtx->sslContext.ctx = NULL;
LogError( ( "Failed to load client-private-key file" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
wolfSSL_CTX_free( pNetCtx->sslContext.ctx );
pNetCtx->sslContext.ctx = NULL;
LogError( ( "Failed to load client-certificate file" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}
else
{
wolfSSL_CTX_free( pNetCtx->sslContext.ctx );
pNetCtx->sslContext.ctx = NULL;
LogError( ( "Failed to load ca-certificate file" ) );
LogError( ( "Failed to load credentials" ) );
returnStatus = TLS_TRANSPORT_INVALID_CREDENTIALS;
}
}