Skip to content

Dynamic SSL/TLS context switching for Mtls context aggregation between peer bmc#1401

Open
priyair wants to merge 1 commit intoibm-openbmc:1210from
priyair:mtls-context-aggregation
Open

Dynamic SSL/TLS context switching for Mtls context aggregation between peer bmc#1401
priyair wants to merge 1 commit intoibm-openbmc:1210from
priyair:mtls-context-aggregation

Conversation

@priyair
Copy link
Copy Markdown
Collaborator

@priyair priyair commented Feb 16, 2026

This pull request supersedes #1395.
This patch implements dynamic SSL/TLS context switching
in bmcweb. The implementation maintains two separate SSL
contexts:

- HTTPS context: standard TLS with optional client
  certificate
- mTLS context: mutual TLS requiring mandatory client
  certificate authentication

The server selects the appropriate context based on the
client's Server Name Indication (SNI). This enables
secure peer-to-peer Redfish aggregation while continuing
to support standard HTTPS clients on same port.

Tested By:
    '''

        - Configured peer BMC aggregation using JSON
        configuration files
        - Verified requests from client BMCs with
        TLS strict mode both enabled and disabled
        - Tested with client certificates and
        authentication tokens
        - HTTPS and mTLS connections are correctly
        established and switched based on SNI

1. Token-based authentication with tlsStrict=false:
   curl -k -H "X-Auth-Token: $bmc_token24" -X GET \
     https://<bmc>/redfish/v1/Systems

2. Certificate upload to Truststore:
   curl -k -H "X-Auth-Token: $bmc_token26" -X POST \
     https://<bmc26>/redfish/v1/bmc/Truststore/Certificates \
     -H "Content-Type: application/json" \
     -d '{"CertificateType": "PEM",
          "CertificateString": "'"$CERT_STRING"'"}'

3. Certificate replacement:
   curl -k -H "X-Auth-Token: $bmc_token26" -X POST \
     https://<bmc26>/redfish/v1/bmc/CertificateService.ReplaceCertificate \
     -H "Content-Type: application/json" -d '{
       "CertificateType": "PEM",
       "CertificateString": "'"$CERT_STRING"'",
      "CertificateUri": {
         "@odata.id": "/redfish/v1/HTTPS/Certificates/1"
       }
     }'

4. mTLS authentication with tlsStrict=false:
   curl -v --cert client.pem \
     --cacert ../serverCA/ca.crt \
     https://<bmc>/redfish/v1/Systems

5. Token-based authentication with tlsStrict=true:
   curl -k -H "X-Auth-Token: $bmc_token24" -X GET \
     https://<bmc>/redfish/v1/Systems

6. mTLS authentication with tlsStrict=true:
   curl -v --cert client.pem \
     --cacert ../serverCA/ca.crt \
     https://<bmc>/redfish/v1/Systems
        '''
    '''

@priyair priyair force-pushed the mtls-context-aggregation branch from fa93b93 to 70d6721 Compare February 16, 2026 22:00
Copy link
Copy Markdown
Collaborator Author

@priyair priyair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request supersedes #1395.

Comment thread src/ssl_key_handler.cpp Outdated

// Keep context pair alive
static std::unique_ptr<SslContextPair> s_ctxPair;
s_ctxPair = std::move(ctxPair);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the use of static ? we are always recreating ctxPair here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the use of static ? we are always recreating ctxPair here

Removed static and created SslContextPair with both HTTPS and mTLS contexts for TLS handshake.

Comment thread src/ssl_key_handler.cpp
}

// Common helper
void setVerifyMode(const std::shared_ptr<boost::asio::ssl::context>& ctx,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we need this function?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setVerifyMode() is called during context initialization (before connections)

Comment thread src/ssl_key_handler.cpp Outdated

SSL_set_SSL_CTX(ssl, newCtx);

if (strict)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we not using setVarifymode function declared above?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we not using setVarifymode function declared above?

switchSslContext() is called during active SSL handshake (per-connection)

Comment thread src/ssl_key_handler.cpp Outdated
// Determine if this should be mTLS based on SNI
if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &sni,
&sniLen) == 1 &&
sniLen > 5)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move below line in to separate function?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move below line in to separate function?

Done, moved to function std::string hostname =
mtls_SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);

Comment thread src/ssl_key_handler.cpp
g_contextPairIndex =
SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think 'call-once' may be done more smoothly & clearly by doing like this.

#include <mutex>

std::once_flag exDataIndex_flag;

static void initializeExDataIndex()
{
   std::call_once( exDataIndex_flag, 
      [](){
            g_contextPairIndex =
            SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
    });
 }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread src/ssl_key_handler.cpp Outdated
// Create mTLS server context
static std::shared_ptr<boost::asio::ssl::context> getSslMtlsServerContext()
{
using namespace boost::asio::ssl;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use the full namespace for the related ones for the clear references?

  • boost::asio::ssl::context::tls_server

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use the full namespace for the related ones for the clear references?

  • boost::asio::ssl::context::tls_server

Done

This patch implements dynamic SSL/TLS context switching
in bmcweb. The implementation maintains two separate SSL
contexts:

- HTTPS context: standard TLS with optional client
  certificate
- mTLS context: mutual TLS requiring mandatory client
  certificate authentication

The server selects the appropriate context based on the
client's Server Name Indication (SNI). This enables
secure peer-to-peer Redfish aggregation while continuing
to support standard HTTPS clients on same port.

    Tested By:
        '''
	- Configured peer BMC aggregation using JSON
  	configuration files
	- Verified requests from client BMCs with
	TLS strict mode both enabled and disabled
	- Tested with client certificates and
	authentication tokens
	- HTTPS and mTLS connections are correctly
	established and switched based on SNI

1. Token-based authentication with tlsStrict=false:
   curl -k -H "X-Auth-Token: $bmc_token24" -X GET \
     https://<bmc>/redfish/v1/Systems

2. Certificate upload to Truststore:
   curl -k -H "X-Auth-Token: $bmc_token26" -X POST \
     https://<bmc26>/redfish/v1/bmc/Truststore/Certificates \
     -H "Content-Type: application/json" \
     -d '{"CertificateType": "PEM",
          "CertificateString": "'"$CERT_STRING"'"}'

3. Certificate replacement:
   curl -k -H "X-Auth-Token: $bmc_token26" -X POST \
     https://<bmc26>/redfish/v1/bmc/CertificateService.ReplaceCertificate \
     -H "Content-Type: application/json" -d '{
       "CertificateType": "PEM",
       "CertificateString": "'"$CERT_STRING"'",
       "CertificateUri": {
         "@odata.id": "/redfish/v1/HTTPS/Certificates/1"
       }
     }'

4. mTLS authentication with tlsStrict=false:
   curl -v --cert client.pem \
     --cacert ../serverCA/ca.crt \
     https://<bmc>/redfish/v1/Systems

5. Token-based authentication with tlsStrict=true:
   curl -k -H "X-Auth-Token: $bmc_token24" -X GET \
     https://<bmc>/redfish/v1/Systems

6. mTLS authentication with tlsStrict=true:
   curl -v --cert client.pem \
     --cacert ../serverCA/ca.crt \
     https://<bmc>/redfish/v1/Systems
        '''

Change-Id: I49c8f3d69d4b91a3a1ebe9b5f001943d5f1f47f8
@priyair priyair force-pushed the mtls-context-aggregation branch from 5468096 to ca209e6 Compare February 23, 2026 13:06
Copy link
Copy Markdown
Contributor

@baemyung baemyung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me.
BTW, I think it is better to add upstream gerrit commit link here.

@priyair
Copy link
Copy Markdown
Collaborator Author

priyair commented Feb 24, 2026

It looks good to me. BTW, I think it is better to add upstream gerrit commit link here.

https://gerrit.openbmc.org/c/openbmc/bmcweb/+/87711

Copy link
Copy Markdown
Contributor

@gtmills gtmills left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep going upstream here?

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