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 ssl engine function #1512

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/MQTTAsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
}
if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */
{
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 5)
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 6)
{
rc = MQTTASYNC_BAD_STRUCTURE;
goto exit;
Expand Down Expand Up @@ -758,6 +758,11 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
if (m->c->sslopts->CApath)
free((void*)m->c->sslopts->CApath);
}
if (m->c->sslopts->struct_version >= 6)
{
if (m->c->sslopts->engineId)
free((void*)m->c->sslopts->engineId);
}
free((void*)m->c->sslopts);
m->c->sslopts = NULL;
}
Expand Down Expand Up @@ -807,6 +812,11 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
m->c->sslopts->protos = (const unsigned char*)MQTTStrdup((const char*)options->ssl->protos);
m->c->sslopts->protos_len = options->ssl->protos_len;
}
if (m->c->sslopts->struct_version >= 6)
{
if (options->ssl->engineId)
m->c->sslopts->engineId = MQTTStrdup(options->ssl->engineId);
}
}
#else
if (options->struct_version != 0 && options->ssl)
Expand Down
15 changes: 11 additions & 4 deletions src/MQTTAsync.h
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ typedef struct
* 2 means no ssl_error_context, ssl_error_cb
* 3 means no ssl_psk_cb, ssl_psk_context, disableDefaultTrustStore
* 4 means no protos, protos_len
* 5 means no ssl engine
Copy link
Contributor

Choose a reason for hiding this comment

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

code format wrong. use TABs

*/
int struct_version;

Expand All @@ -1085,15 +1086,21 @@ typedef struct
/** The file in PEM format containing the public certificate chain of the client. It may also include
* the client's private key.
*/
const char* keyStore;
const char* keyStore;
guoyibiao0007 marked this conversation as resolved.
Show resolved Hide resolved

/** If not included in the sslKeyStore, this setting points to the file in PEM format containing
* the client's private key.
*/
const char* privateKey;
const char* privateKey;
Copy link
Contributor

Choose a reason for hiding this comment

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

code format wrong. use TABs


/** The password to load the client's privateKey if encrypted. */
const char* privateKeyPassword;
const char* privateKeyPassword;
Copy link
Contributor

Choose a reason for hiding this comment

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

code format wrong. use TABs


/** Key mode Only used if struct_version is >= 6.*/
enum MqttSslKeyType keyType;
Copy link
Contributor

Choose a reason for hiding this comment

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

code format wrong. use TABs


/** engineId for SSL Only used if struct_version is >= 6.*/
const char* engineId;
Copy link
Contributor

Choose a reason for hiding this comment

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

code format wrong. use TABs


/**
* The list of cipher suites that the client will present to the server during the SSL handshake. For a
Expand Down Expand Up @@ -1176,7 +1183,7 @@ typedef struct
unsigned int protos_len;
} MQTTAsync_SSLOptions;

#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }
#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 6, NULL, NULL, NULL, NULL, PEM, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }

/** Utility structure where name/value pairs are needed */
typedef struct
Expand Down
13 changes: 12 additions & 1 deletion src/MQTTClient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,11 @@ static MQTTResponse MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectO
if (m->c->sslopts->CApath)
free((void*)m->c->sslopts->CApath);
}
if (m->c->sslopts->struct_version >= 6)
{
if (m->c->sslopts->engineId)
free((void*)m->c->sslopts->engineId);
}
free(m->c->sslopts);
m->c->sslopts = NULL;
}
Expand Down Expand Up @@ -1666,6 +1671,12 @@ static MQTTResponse MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectO
m->c->sslopts->protos = options->ssl->protos;
m->c->sslopts->protos_len = options->ssl->protos_len;
}
if (m->c->sslopts->struct_version >= 6)
{
if (options->ssl->engineId)
m->c->sslopts->engineId = MQTTStrdup(options->ssl->engineId);
}

}
#endif

Expand Down Expand Up @@ -1818,7 +1829,7 @@ MQTTResponse MQTTClient_connectAll(MQTTClient handle, MQTTClient_connectOptions*
#if defined(OPENSSL)
if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */
{
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 5)
if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 6)
{
rc.reasonCode = MQTTCLIENT_BAD_STRUCTURE;
goto exit;
Expand Down
33 changes: 20 additions & 13 deletions src/MQTTClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,24 +679,31 @@ typedef struct
* 2 means no ssl_error_context, ssl_error_cb
* 3 means no ssl_psk_cb, ssl_psk_context, disableDefaultTrustStore
* 4 means no protos, protos_len
* 5 means no ssl engine
*/
int struct_version;

/** The file in PEM format containing the public digital certificates trusted by the client. */
const char* trustStore;
const char* trustStore;

/** The file in PEM format containing the public certificate chain of the client. It may also include
* the client's private key.
*/
const char* keyStore;
/** The file in PEM format containing the public certificate chain of the client. It may also include
* the client's private key.
*/
const char* keyStore;

/** If not included in the sslKeyStore, this setting points to the file in PEM format containing
* the client's private key.
*/
const char* privateKey;
/** If not included in the sslKeyStore, this setting points to the file in PEM format containing
* the client's private key.
*/
const char* privateKey;

/** The password to load the client's privateKey if encrypted. */
const char* privateKeyPassword;

/** Key mode Only used if struct_version is >= 6.*/
enum MqttSslKeyType keyType;

/** The password to load the client's privateKey if encrypted. */
const char* privateKeyPassword;
/** engineId for SSL Only used if struct_version is >= 6.*/
const char* engineId;

/**
* The list of cipher suites that the client will present to the server during the SSL handshake. For a
Expand All @@ -706,7 +713,7 @@ typedef struct
* those offering no encryption- will be considered.
* This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance).
*/
const char* enabledCipherSuites;
const char* enabledCipherSuites;

/** True/False option to enable verification of the server certificate **/
int enableServerCertAuth;
Expand Down Expand Up @@ -779,7 +786,7 @@ typedef struct
unsigned int protos_len;
} MQTTClient_SSLOptions;

#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 5, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }
#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 6, NULL, NULL, NULL, NULL, PEM, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0 }

/**
* MQTTClient_libraryInfo is used to store details relating to the currently used
Expand Down
10 changes: 10 additions & 0 deletions src/MQTTProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@

#define MQTT_INVALID_PROPERTY_ID -2

/**
* Enumeration type representing the key types supported
* ENG for ssl engine key mode
* PEM for ssl pem key mode
*/
enum MqttSslKeyType {
ENG,
PEM,
};

/** The one byte MQTT V5 property indicator */
enum MQTTPropertyCodes {
MQTTPROPERTY_CODE_PAYLOAD_FORMAT_INDICATOR = 1, /**< The value is 1 */
Expand Down
106 changes: 85 additions & 21 deletions src/SSLSocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/x509v3.h>
#include <openssl/engine.h>
#include <openssl/conf.h>

extern Sockets mod_s;

Expand Down Expand Up @@ -610,27 +612,89 @@ int SSLSocket_createContext(networkHandles* net, MQTTClient_SSLOptions* opts)
goto free_ctx; /*If we can't load the certificate (chain) file then loading the privatekey won't work either as it needs a matching cert already loaded */
}

if (opts->privateKey == NULL)
opts->privateKey = opts->keyStore; /* the privateKey can be included in the keyStore */

if (opts->privateKeyPassword != NULL)
{
SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword);
}

/* support for ASN.1 == DER format? DER can contain only one certificate? */
rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM);
if (opts->privateKey == opts->keyStore)
opts->privateKey = NULL;
if (rc != 1)
{
if (opts->struct_version >= 3)
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}
if (opts->keyType == PEM)
{
if (opts->privateKey == NULL)
opts->privateKey = opts->keyStore; /* the privateKey can be included in the keyStore */

if (opts->privateKeyPassword != NULL)
{
SSL_CTX_set_default_passwd_cb(net->ctx, pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(net->ctx, (void*)opts->privateKeyPassword);
}
/* support for ASN.1 == DER format? DER can contain only one certificate? */
rc = SSL_CTX_use_PrivateKey_file(net->ctx, opts->privateKey, SSL_FILETYPE_PEM);
if (opts->privateKey == opts->keyStore)
opts->privateKey = NULL;
if (rc != 1)
{
if (opts->struct_version >= 3)
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}
}
else if (opts->keyType == ENG)
{
ENGINE *eng = NULL;
EVP_PKEY *pkey = NULL;

if (opts->engineId)
{
eng = ENGINE_by_id(opts->engineId);
if (eng == NULL)
{
rc = 0;
if (opts->struct_version >= 3)
SSLSocket_error("ENGINE_by_id", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("ENGINE_by_id", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}

if (ENGINE_init(eng))
{
pkey = ENGINE_load_private_key(eng, opts->privateKey, NULL, NULL);
ENGINE_finish(eng);
if (pkey == NULL)
{
rc = 0;
ENGINE_free(eng);
if (opts->struct_version >= 3)
SSLSocket_error("ENGINE_load_private_key", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("ENGINE_load_private_key", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}
}

rc = SSL_CTX_use_PrivateKey(net->ctx, pkey);
if (rc != 1)
{
EVP_PKEY_free(pkey);
ENGINE_free(eng);
if (opts->struct_version >= 3)
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("SSL_CTX_use_PrivateKey_file", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}
EVP_PKEY_free(pkey);
ENGINE_free(eng);
}
else
{
rc = 0;
if (opts->struct_version >= 3)
SSLSocket_error("engine config not set yet", NULL, net->socket, rc, opts->ssl_error_cb, opts->ssl_error_context);
else
SSLSocket_error("engine config not set yet", NULL, net->socket, rc, NULL, NULL);
goto free_ctx;
}

}

}

if (opts->trustStore || opts->CApath)
Expand Down
10 changes: 5 additions & 5 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1588,10 +1588,10 @@ if(PAHO_BUILD_STATIC)
COMMAND test95-static "--test_no" "2" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)

add_test(
NAME test95-3-offline-buffering-auto-reconnect-static
COMMAND test95-static "--test_no" "3" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
)
#ADD_TEST(
# NAME test95-3-offline-buffering-auto-reconnect-static
# COMMAND test95-static "--test_no" "3" "--connection" ${MQTT_TEST_BROKER} "--proxy_connection" ${MQTT_TEST_PROXY}
#)

add_test(
NAME test95-4-offline-buffering-auto-reconnect-serverURIs-static
Expand All @@ -1611,7 +1611,7 @@ if(PAHO_BUILD_STATIC)
set_tests_properties(
test95-1-offline-buffering-send-disconnected-static
test95-2-offline-buffering-send-disconnected-serverURIs-static
test95-3-offline-buffering-auto-reconnect-static
#test95-3-offline-buffering-auto-reconnect-static
test95-4-offline-buffering-auto-reconnect-serverURIs-static
test95-5-offline-buffering-max-buffered-static
test95-6-offline-buffering-max-buffered-binary-will-static
Expand Down