Skip to content

Commit 6fff6ef

Browse files
committed
Add support for reading Root CA Certificates from a pkcs11 module.
Escape semicolons in config definitions that might be pkcs11 URIs.
1 parent 1714fd9 commit 6fff6ef

File tree

3 files changed

+150
-62
lines changed

3 files changed

+150
-62
lines changed

CMakeLists.txt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,28 @@ set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
6565
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
6666
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
6767

68+
if(DEFINED ROOT_CA_CERT_PATH)
69+
string(REPLACE ";" "\\$<SEMICOLON>" ROOT_CA_CERT_PATH "${ROOT_CA_CERT_PATH}")
70+
endif()
71+
72+
if(DEFINED CLIENT_CERT_PATH)
73+
string(REPLACE ";" "\\$<SEMICOLON>" CLIENT_CERT_PATH "${CLIENT_CERT_PATH}")
74+
endif()
75+
76+
if(DEFINED CLIENT_PRIVATE_KEY_PATH)
77+
string(REPLACE ";" "\\$<SEMICOLON>" CLIENT_PRIVATE_KEY_PATH "${CLIENT_PRIVATE_KEY_PATH}")
78+
endif()
79+
6880
# Set prefix to PWD if any path flags are relative.
6981
# PWD is set to the path where you run the cmake command.
7082
if(DEFINED ENV{PWD})
71-
if(ROOT_CA_CERT_PATH AND NOT IS_ABSOLUTE ${ROOT_CA_CERT_PATH})
83+
if(DEFINED ROOT_CA_CERT_PATH AND NOT ROOT_CA_CERT_PATH MATCHES "^pkcs11.+$" AND NOT IS_ABSOLUTE ${ROOT_CA_CERT_PATH})
7284
set(ROOT_CA_CERT_PATH "$ENV{PWD}/${ROOT_CA_CERT_PATH}")
7385
endif()
74-
if(CLIENT_CERT_PATH AND NOT IS_ABSOLUTE ${CLIENT_CERT_PATH})
86+
if(DEFINED CLIENT_CERT_PATH AND NOT CLIENT_CERT_PATH MATCHES "^pkcs11.+$" AND NOT IS_ABSOLUTE ${CLIENT_CERT_PATH})
7587
set(CLIENT_CERT_PATH "$ENV{PWD}/${CLIENT_CERT_PATH}")
7688
endif()
77-
if(CLIENT_PRIVATE_KEY_PATH AND NOT IS_ABSOLUTE ${CLIENT_PRIVATE_KEY_PATH})
89+
if(DEFINED CLIENT_PRIVATE_KEY_PATH AND NOT CLIENT_PRIVATE_KEY_PATH MATCHES "^pkcs11.+$" AND NOT IS_ABSOLUTE ${CLIENT_PRIVATE_KEY_PATH})
7890
set(CLIENT_PRIVATE_KEY_PATH "$ENV{PWD}/${CLIENT_PRIVATE_KEY_PATH}")
7991
endif()
8092
endif()

platform/posix/transport/src/openssl_posix.c

Lines changed: 133 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,29 @@ struct NetworkContext
9191
static int32_t opensslError( void );
9292

9393
/**
94-
* @brief Add X509 certificate to the trusted list of root certificates.
95-
*
96-
* OpenSSL does not provide a single function for reading and loading
97-
* certificates from files into stores, so the file API must be called. Start
98-
* with the root certificate.
94+
* @brief Add X509 certificate from a file to the trusted list of root certificates.
9995
*
10096
* @param[out] pSslContext SSL context to which the trusted server root CA is to
10197
* be added.
10298
* @param[in] pRootCaPath Filepath string to the trusted server root CA.
10399
*
104100
* @return 1 on success; -1, 0 on failure.
105101
*/
106-
static int32_t setRootCa( const SSL_CTX * pSslContext,
107-
const char * pRootCaPath );
102+
static int32_t setRootCaFromFile( const SSL_CTX * pSslContext,
103+
const char * pRootCaPath );
104+
105+
/**
106+
* @brief Add X509 certificate from a PKCS#11 token to the trusted list of root certificates.
107+
*
108+
* @param[out] pSslContext SSL context to which the trusted server root CA is to
109+
* be added.
110+
* @param[in] pRootCaURI Filepath string to the trusted server root CA.
111+
*
112+
* @return 1 on success; -1, 0 on failure.
113+
*/
114+
static int32_t setRootCaFromPkcs11( const SSL_CTX * pSslContext,
115+
ENGINE * pEngine,
116+
const char * pRootCaURI );
108117

109118
/**
110119
* @brief Load an X509 client certificate from a given file.
@@ -123,13 +132,13 @@ static int32_t setClientCertificateFromFile( SSL_CTX * pSslContext,
123132
*
124133
* @param[out] pSslContext SSL context to which the client certificate is to be
125134
* set.
126-
* @param[in] pClientCertPath PKCS11 URI string for the client certificate object.
135+
* @param[in] pClientCertURI PKCS11 URI string for the client certificate object.
127136
*
128137
* @return 1 on success; 0 failure.
129138
*/
130139
static int32_t setClientCertificateFromPkcs11( SSL_CTX * pSslContext,
131140
ENGINE * pEngine,
132-
const char * pClientCertPath );
141+
const char * pClientCertURI );
133142

134143
/**
135144
* @brief Load a private key into the ssl context from a given file path.
@@ -147,7 +156,7 @@ static int32_t setPrivateKeyFromFile( SSL_CTX * pSslContext,
147156
*
148157
* @param[out] pSslContext SSL context to add the private key to.
149158
* @param[in] pEngine Openssl engine handle to read the key from.
150-
* @param[in] pPrivateKeyPath PKCS#11 URI to load the private key from.
159+
* @param[in] pPrivateKeyURI PKCS#11 URI to load the private key from.
151160
*
152161
* @return 1 on success; 0 on failure.
153162
*/
@@ -355,8 +364,9 @@ static OpensslStatus_t tlsHandshake( const ServerInfo_t * pServerInfo,
355364

356365
return returnStatus;
357366
}
367+
/*-----------------------------------------------------------*/
358368

359-
static int32_t setRootCa( const SSL_CTX * pSslContext,
369+
static int32_t setRootCaFromFile( const SSL_CTX * pSslContext,
360370
const char * pRootCaPath )
361371
{
362372
int32_t sslStatus = 1;
@@ -445,6 +455,79 @@ static int32_t setRootCa( const SSL_CTX * pSslContext,
445455
}
446456
/*-----------------------------------------------------------*/
447457

458+
static int32_t loadCertificateFromPkcs11( X509 ** ppX509Cert,
459+
ENGINE * pEngine,
460+
const char * pCertURI )
461+
{
462+
int32_t sslStatus = 1;
463+
struct
464+
{
465+
const char * pCertURI;
466+
X509 * pX509Cert;
467+
} loadCertParams;
468+
469+
assert( ppX509Cert != NULL );
470+
assert( pEngine != NULL );
471+
assert( pCertURI != NULL );
472+
473+
loadCertParams.pCertURI = pCertURI;
474+
loadCertParams.pX509Cert = NULL;
475+
476+
sslStatus = ENGINE_ctrl_cmd( pEngine, "LOAD_CERT_CTRL", 0,
477+
&loadCertParams, NULL, 0 );
478+
479+
if( loadCertParams.pX509Cert == NULL )
480+
{
481+
LogError( ( "ENGINE_ctrl_cmd returned an empty certificate object "
482+
"from URI: %s .", pCertURI ) );
483+
sslStatus = 0;
484+
}
485+
else if( sslStatus != 1 )
486+
{
487+
LogError( ( "ENGINE_ctrl_cmd failed to read "
488+
"certificate from URI: %s .", pCertURI ) );
489+
sslStatus = opensslError();
490+
}
491+
else
492+
{
493+
*ppX509Cert = loadCertParams.pX509Cert;
494+
}
495+
return sslStatus;
496+
}
497+
/*-----------------------------------------------------------*/
498+
499+
static int32_t setRootCaFromPkcs11( const SSL_CTX * pSslContext,
500+
ENGINE * pEngine,
501+
const char * pRootCaURI )
502+
{
503+
int32_t sslStatus = 1;
504+
X509 * pRootCa = NULL;
505+
506+
assert( pSslContext != NULL );
507+
assert( pEngine != NULL );
508+
assert( pRootCaURI != NULL );
509+
510+
sslStatus = loadCertificateFromPkcs11( &pRootCa, pEngine, pRootCaURI );
511+
512+
if( sslStatus == 1 )
513+
{
514+
LogInfo( ( "Successfully read client certificate from URI: %s .",
515+
pClientCertURI ) );
516+
517+
/* Import cert into context */
518+
sslStatus = X509_STORE_add_cert( SSL_CTX_get_cert_store( pSslContext ), pRootCa );
519+
520+
if( sslStatus != 1 )
521+
{
522+
LogError( ( "Failed to add Root CA certificate to SSL context from URI : %s .",
523+
pRootCaURI ) );
524+
}
525+
}
526+
527+
return sslStatus;
528+
}
529+
/*-----------------------------------------------------------*/
530+
448531
static int32_t setClientCertificateFromFile( SSL_CTX * pSslContext,
449532
const char * pClientCertPath )
450533
{
@@ -481,47 +564,27 @@ static int32_t setClientCertificateFromPkcs11( SSL_CTX * pSslContext,
481564
const char * pClientCertURI )
482565
{
483566
int32_t sslStatus = 1;
484-
struct
485-
{
486-
const char * pCertURI;
487-
X509 * pX509Cert;
488-
} loadCertParams;
567+
X509 * pX509Cert = NULL;
489568

490569
assert( pSslContext != NULL );
491570
assert( pEngine != NULL );
492571
assert( pClientCertURI != NULL );
493572

494-
loadCertParams.pCertURI = pClientCertURI;
495-
loadCertParams.pX509Cert = NULL;
573+
sslStatus = loadCertificateFromPkcs11( &pX509Cert, pEngine, pClientCertURI );
496574

497-
sslStatus = ENGINE_ctrl_cmd( pEngine, "LOAD_CERT_CTRL", 0,
498-
&loadCertParams, NULL, 0 );
499-
500-
if( loadCertParams.pX509Cert == NULL )
501-
{
502-
LogError( ( "ENGINE_ctrl_cmd returned an empty certificate object "
503-
"from URI: %s .", pClientCertURI ) );
504-
sslStatus = 0;
505-
}
506-
else if( sslStatus != 1 )
507-
{
508-
LogError( ( "ENGINE_ctrl_cmd failed to read client "
509-
"certificate from URI: %s .", pClientCertURI ) );
510-
sslStatus = opensslError();
511-
}
512-
else
575+
if( sslStatus == 1 )
513576
{
514577
LogInfo( ( "Successfully read client certificate from URI: %s .",
515578
pClientCertURI ) );
516579

517580
/* Import cert into context */
518-
sslStatus = SSL_CTX_use_certificate( pSslContext, loadCertParams.pX509Cert );
519-
}
581+
sslStatus = SSL_CTX_use_certificate( pSslContext, pX509Cert );
520582

521-
if( sslStatus != 1 )
522-
{
523-
LogError( ( "Failed to copy certificate into SSL context from URI : %s .",
524-
pClientCertURI ) );
583+
if( sslStatus != 1 )
584+
{
585+
LogError( ( "Failed to copy certificate into SSL context from URI : %s .",
586+
pClientCertURI ) );
587+
}
525588
}
526589

527590
return sslStatus;
@@ -636,9 +699,6 @@ static int32_t initializePkcs11Engine( ENGINE ** ppEngine,
636699

637700
assert( ppEngine != NULL );
638701

639-
/* Initialize pkcs11 config and engine */
640-
// ENGINE_add_conf_module();
641-
642702
ENGINE_load_builtin_engines();
643703

644704
/* Acquire a structural reference for the pkcs11 engine */
@@ -708,45 +768,61 @@ static int32_t setCredentials( SSL_CTX * pSslContext,
708768
{
709769
int32_t sslStatus = 1;
710770
ENGINE * pEngine = NULL;
711-
bool certFromEngine = false;
712-
bool pkeyFromEngine = false;
771+
bool certFromP11 = false;
772+
bool pkeyFromP11 = false;
773+
bool rootCaFromP11 = false;
713774

714775
assert( pSslContext != NULL );
715776
assert( pOpensslCredentials != NULL );
716777

717-
if( pOpensslCredentials->pRootCaPath != NULL )
718-
{
719-
sslStatus = setRootCa( pSslContext, pOpensslCredentials->pRootCaPath );
720-
}
721-
722778
/* Initialize the pkcs11 engine if needed */
723-
if( ( sslStatus == 1 ) &&
724-
( pOpensslCredentials->pPrivateKeyPath != NULL ) &&
779+
if( ( pOpensslCredentials->pPrivateKeyPath != NULL ) &&
725780
( pOpensslCredentials->pClientCertPath != NULL ) )
726781
{
727782
if( strncmp( pOpensslCredentials->pPrivateKeyPath,
728783
PKCS11_URI_PREFIX, sizeof( PKCS11_URI_PREFIX ) - 1 ) == 0 )
729784
{
730-
pkeyFromEngine = true;
785+
pkeyFromP11 = true;
786+
}
787+
788+
if( strncmp( pOpensslCredentials->pRootCaPath,
789+
PKCS11_URI_PREFIX, sizeof( PKCS11_URI_PREFIX ) - 1 ) == 0 )
790+
{
791+
rootCaFromP11 = true;
731792
}
732793

733794
if( strncmp( pOpensslCredentials->pClientCertPath,
734795
PKCS11_URI_PREFIX, sizeof( PKCS11_URI_PREFIX ) - 1 ) == 0 )
735796
{
736-
certFromEngine = true;
797+
certFromP11 = true;
737798
}
738799

739-
if( pkeyFromEngine == true || certFromEngine == true )
800+
if( pkeyFromP11 == true || certFromP11 == true || rootCaFromP11 == true )
740801
{
741802
sslStatus = initializePkcs11Engine( &pEngine,
742803
pOpensslCredentials->pP11ModulePath,
743804
pOpensslCredentials->pP11ModulePin );
744805
}
745806
}
746807

808+
if( ( sslStatus == 1 ) && ( pOpensslCredentials->pRootCaPath != NULL ) )
809+
{
810+
if( rootCaFromP11 == true )
811+
{
812+
sslStatus = setRootCaFromPkcs11( pSslContext,
813+
pEngine,
814+
pOpensslCredentials->pRootCaPath );
815+
}
816+
else
817+
{
818+
sslStatus = setRootCaFromFile( pSslContext,
819+
pOpensslCredentials->pRootCaPath );
820+
}
821+
}
822+
747823
if( ( sslStatus == 1 ) && ( pOpensslCredentials->pClientCertPath != NULL ) )
748824
{
749-
if( pkeyFromEngine == true )
825+
if( pkeyFromP11 == true )
750826
{
751827
sslStatus = setClientCertificateFromPkcs11( pSslContext,
752828
pEngine,
@@ -761,7 +837,7 @@ static int32_t setCredentials( SSL_CTX * pSslContext,
761837

762838
if( ( sslStatus == 1 ) && ( pOpensslCredentials->pPrivateKeyPath != NULL ) )
763839
{
764-
if( pkeyFromEngine == true )
840+
if( pkeyFromP11 == true )
765841
{
766842
sslStatus = setPrivateKeyFromPkcs11( pSslContext,
767843
pEngine,

tools/cmake/utility.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function(set_macro_definitions)
2929
# Compile the application with the macro definition if it is defined.
3030
target_compile_definitions(
3131
${application_target} PRIVATE
32-
${optional_macro_definition}="${${optional_macro_definition}}"
32+
"${optional_macro_definition}=\"${${optional_macro_definition}}\""
3333
)
3434
list(APPEND DEFINED_MACROS_FROM_CMAKE "${optional_macro_definition}")
3535
endif()
@@ -41,7 +41,7 @@ function(set_macro_definitions)
4141
if(DEFINED ${required_macro_definition})
4242
target_compile_definitions(
4343
${application_target} PRIVATE
44-
${required_macro_definition}="${${required_macro_definition}}"
44+
"${required_macro_definition}=\"${${required_macro_definition}}\""
4545
)
4646
# This variable adds definitions to the file being run against `check_symbol_exists`.
4747
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D${required_macro_definition})

0 commit comments

Comments
 (0)