Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add secure socket layer options for modem ports #147

Closed
wants to merge 11 commits into from

Conversation

chinglee-iot
Copy link
Member

Description

Cellular modem may support secure socket connection with modem specific APIs. This PR adds the secure socket layer options to enable secure socket connection with port layer APIs. Port has to implements the following functions with board specific AT commands:

  • Upload credentials to cellular modem
  • Configure secure socket context
  • Store the secure socket options in socket context

For example, BG96 can define the following APIs in cellular_bg96_api.h for user to include and implement these APIs in cellular_bg96_api.c.

/* Upload credential to the file system. Later it can be used to configure the secure socket context. */                                              
CellularError_t Cellular_UploadFileToStorage( CellularHandle_t cellularHandle,
                                              const char* filename,
                                              const char* fileContent,
                                              uint32_t fileSize,
                                              uint32_t* pSentDataLength );

/* Configure the secure socket context. */
CellularError_t Cellular_ConfigureSSLContext( CellularHandle_t cellularHandle,
                                              uint8_t sslContextId,
                                              const char* sslConfigurationParameter,
                                              const char* inputArg );

BG96 has to support CELLULAR_SOCKET_OPTION_SSL_CONTEXT_ID and CELLULAR_SOCKET_OPTION_SSL_USAGE in the implementation of Cellular_SocketSetSockOpt. For example,

typedef struct CellularSocketSslConfig
{
    uint8_t useSsl;
    uint8_t sslContextId;
} CellularSocketSslConfig_t;

static CellularSocketSslConfig_t cellularSocketSslConfig[ CELLULAR_NUM_SOCKET_MAX ];

CellularError_t Cellular_CreateSocket( CellularHandle_t cellularHandle,
                                       uint8_t pdnContextId,
                                       CellularSocketDomain_t socketDomain,
                                       CellularSocketType_t socketType,
                                       CellularSocketProtocol_t socketProtocol,
                                       CellularSocketHandle_t * pSocketHandle )
{
    CellularError_t cellularStatus;
    CellularSocketContext_t * pSocketContext;

    cellularStatus = Cellular_CommonCreateSocket( cellularHandle, pdnContextId, socketDomain, socketType,
                                                  socketProtocol, pSocketHandle );
    if( cellularStatus == CELLULAR_SUCCESS )
    {
        /* pSocketHandle is checked in Cellular_CommonCreateSocket already. */
        pSocketContext = ( CellularSocketContext_t * )pSocketHandle;
        /* Make use of pModemData to store modem specific socket data. */
        pSocketContext->pModemData = &( cellularSocketSslConfig[ socketIndex ] );
    }
}

CellularError_t Cellular_SocketSetSockOpt( CellularHandle_t cellularHandle,
                                           CellularSocketHandle_t socketHandle,
                                           CellularSocketOptionLevel_t optionLevel,
                                           CellularSocketOption_t option,
                                           const uint8_t * pOptionValue,
                                           uint32_t optionValueLength )
{
    CellularError_t cellularStatus;
    CellularSocketContext_t * pSocketContext;
    CellularSocketSslConfig_t * pSocketSslConfig;

    cellularStatus = Cellular_CommonSocketSetSockOpt( cellularHandle, socketHandle, optionLevel, option,
                                            pOptionValue, optionValueLength );
    if( cellularStatus == CELLULAR_UNSUPPORTED )
    {
        /* pSocketHandle is checked in Cellular_CommonCreateSocket already. */
        pSocketContext = ( CellularSocketContext_t * )pSocketHandle;
        pSocketSslConfig = ( CellularSocketSslConfig_t * )pSocketContext->pModemData;

        if( optionLevel == CELLULAR_SOCKET_OPTION_LEVEL_SECURE )
        {
            if( option == CELLULAR_SOCKET_OPTION_SSL_CONTEXT_ID )
            {
                if( ( pSocketContext->socketState == SOCKETSTATE_ALLOCATED ) && ( optionValueLength == sizeof( uint8_t ) ) )
                {
                    pSocketSslConfig->sslContextId = *pOptionValue;
                    cellularStatus = CELLULAR_SUCCESS;
                }
                else
                {
                    LogError( ( "Cellular_SocketSetSockOpt: Cannot change the sslContextID in this state %d or length %d is invalid.",
                                pSocketContext->socketState, optionValueLength ) );
                    cellularStatus = CELLULAR_INTERNAL_FAILURE;
                }
            }
            else if( option == CELLULAR_SOCKET_OPTION_SSL_USAGE )
            {
                if( ( pSocketContext->socketState == SOCKETSTATE_ALLOCATED ) && ( optionValueLength == sizeof( uint8_t ) ) )
                {
                    pSocketSslConfig->useSsl = *pOptionValue;
                    cellularStatus = CELLULAR_SUCCESS;
                }
                else
                {
                    LogError( ( "Cellular_SocketSetSockOpt: Cannot change the useSsl in this state %d or length %d is invalid.",
                                pSocketContext->socketState, optionValueLength ) );
                    cellularStatus = CELLULAR_INTERNAL_FAILURE;
                }
            }
            else
            {
                /* This option is also not supported in port. */
            }
        }
        else
        {
            /* This option level is also not supported in port. */
        }
    }
    return cellularStatus;
}

User of cellular interface can make use of port specific APIs to create a secure socket connection with the following example.

#include "cellular_bg96_api.h"
/* Upload the credential to modem storage. Bind the credential with name and type. */
Cellular_UploadFileToStorage( CellularHandle,
                              SERCURITY_PROFILE_NAME_ROOT_CA,
                              pRootCa,
                              rootCaSize,
                              &uxSentDataLength );

Cellular_UploadFileToStorage( CellularHandle,
                              SERCURITY_PROFILE_NAME_CERTIFICATE,
                              pClientCert,
                              clientCertSize,
                              &uxSentDataLength );

Cellular_UploadFileToStorage( CellularHandle,
                              SERCURITY_PROFILE_NAME_PRIVATE_KEY,
                              pPrivateKey,
                              privateKeySize,
                              &uxSentDataLength );

/* Bind the security profile ID with cipher suite and credentials. */
uint8_t sslContextId = 0;
Cellular_ConfigureSSLContext( cellularHandle,
                              sslContextId,
                              "sslversion",
                              "1" );

Cellular_ConfigureSSLContext( cellularHandle,
                              sslContextId,
                              "siphersuite",
                              "0xffff" );

Cellular_ConfigureSSLContext( cellularHandle,
                              sslContextId,
                              "cacert",
                              SERCURITY_PROFILE_NAME_ROOT_CA );

...
/* Create a new TCP socket. */
Cellular_CreateSocket( CellularHandle,
                        CellularSocketPdnContextId,
                        CELLULAR_SOCKET_DOMAIN_AF_INET,
                        CELLULAR_SOCKET_TYPE_STREAM,
                       CELLULAR_SOCKET_PROTOCOL_TCP,
                        &cellularSocketHandle );

Cellular_SocketSetSockOpt( CellularHandle,
                            cellularSocketHandle,
                            CELLULAR_SOCKET_OPTION_LEVEL_SECURE,
                            CELLULAR_SOCKET_OPTION_SSL_CONTEXT_ID,
                            ( const uint8_t * ) &sslContextId,
                            sizeof( uint8_t ) );

sslUsage = 1;
Cellular_SocketSetSockOpt( CellularHandle,
                            cellularSocketHandle,
                            CELLULAR_SOCKET_OPTION_LEVEL_SECURE,
                            CELLULAR_SOCKET_OPTION_SSL_USAGE,
                            ( const uint8_t * ) &sslUsage,
                            sizeof( uint8_t ) );

Cellular_SocketConnect( CellularHandle,
                        cellularSocketHandle,
                        CELLULAR_ACCESSMODE_BUFFER,
                        &serverAddress );

Cellular_SocketSend( CellularHandle,
                      cellularSocketHandle,
                      buf,
                      bytesToSend,
                      &sentLength );

Cellular_SocketRecv( CellularHandle,
                     cellularSocketHandle,
                     buf,
                     len,
                     &recvLength );

Test Steps

Checklist:

  • I have tested my changes. No regression in existing tests.
  • I have modified and/or added unit-tests to cover the code changes in this Pull Request.

Related Issue

#146

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@chinglee-iot
Copy link
Member Author

Close this PR due to no response. Feel free to reopen it if any further update.

@azeater
Copy link

azeater commented Oct 28, 2024

Hi @chinglee-iot, I've tested your changes with the BG96 successfully. What would need to be done to get this PR merged into the main branch? A lot of cellular modules allow for SSL native sockets so I think support would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants