Skip to content

Commit

Permalink
Expand SSLSessionId structure to manage allocated memory. (#1614)
Browse files Browse the repository at this point in the history
!!! Possible breaking changes !!!

	struct SSLKeyCertPair -> class SslKeyCertPair
  		certificate -> getCertificate()
  		certificateLength -> getCertificateLength()
  		key -> getKey()
  		keyLength -> getKeyLength()
	struct SSLSessionId -> class SslSessionId
		value -> getValue()
		length -> getLength()
	SSLFingerprintType -> SslFingerprintType

Deprecated so old version still works with compiler warning:

	SSLFingerprints -> SslFingerprints
	SSLKeyCertPair -> SslKeyCertPair
	SSLSessionId -> SslSessionId


* Expand `SSLSessionId` structure to manage allocated memory.
* Split SSL structures into separate files
* Put all SSL files into `Ssl` sub-folder and create common `SslStructs.h`
* Rename structures from `SSL*` to `Ssl*` for consistency

SSLFingerprints -> SslFingerprints
SSLKeyCertPair -> SslKeyCertPair
SSL SessionId -> SslSessionId

Definitions included for old versions but will generate compiler warning.
* Revised `SslKeyCertPair` and `SslSessionId` to use `String` for storage
Change from `struct` to `class`. Data no longer directly accessible.
  • Loading branch information
mikee47 authored and slaff committed Feb 12, 2019
1 parent 76b288c commit 88a080b
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 181 deletions.
4 changes: 2 additions & 2 deletions Sming/SmingCore/Network/Http/HttpRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ String HttpRequest::toString()
F("> SSL Cert Fingerprint Length: ") + String((sslFingerprint.certSha1 == nullptr) ? 0 : SHA1_SIZE) + '\n';
content +=
F("> SSL PK Fingerprint Length: ") + String((sslFingerprint.pkSha256 == nullptr) ? 0 : SHA256_SIZE) + '\n';
content += F("> SSL ClientCert Length: ") + String(sslKeyCertPair.certificateLength) + '\n';
content += F("> SSL ClientCert PK Length: ") + String(sslKeyCertPair.keyLength) + '\n';
content += F("> SSL ClientCert Length: ") + String(sslKeyCertPair.getCertificateLength()) + '\n';
content += F("> SSL ClientCert PK Length: ") + String(sslKeyCertPair.getKeyLength()) + '\n';
content += '\n';
#endif

Expand Down
10 changes: 5 additions & 5 deletions Sming/SmingCore/Network/Http/HttpRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,11 @@ class HttpRequest
/**
* @brief Requires(pins) the remote SSL certificate to match certain fingerprints
* Check if SHA256 hash of Subject Public Key Info matches the one given.
* @param SSLFingerprints - passes the certificate fingerprints by reference.
* @param fingerprints - passes the certificate fingerprints by reference.
*
* @return bool true of success, false or failure
*/
HttpRequest* pinCertificate(const SSLFingerprints& fingerprints)
HttpRequest* pinCertificate(const SslFingerprints& fingerprints)
{
sslFingerprint = fingerprints;
return this;
Expand All @@ -245,7 +245,7 @@ class HttpRequest
*
* @return HttpRequest pointer
*/
HttpRequest* setSslKeyCert(const SSLKeyCertPair& keyCertPair)
HttpRequest* setSslKeyCert(const SslKeyCertPair& keyCertPair)
{
sslKeyCertPair = keyCertPair;
return this;
Expand Down Expand Up @@ -284,8 +284,8 @@ class HttpRequest

#ifdef ENABLE_SSL
uint32_t sslOptions = 0;
SSLFingerprints sslFingerprint;
SSLKeyCertPair sslKeyCertPair;
SslFingerprints sslFingerprint;
SslKeyCertPair sslKeyCertPair;
#endif

private:
Expand Down
12 changes: 4 additions & 8 deletions Sming/SmingCore/Network/HttpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ bool HttpClient::send(HttpRequest* request)
// Based on the URL decide if we should reuse the SSL and TCP pool
if(useSsl) {
if(!sslSessionIdPool.contains(cacheKey)) {
sslSessionIdPool[cacheKey] = (SSLSessionId*)malloc(sizeof(SSLSessionId));
sslSessionIdPool[cacheKey]->value = NULL;
sslSessionIdPool[cacheKey]->length = 0;
sslSessionIdPool[cacheKey] = new SslSessionId;
}
httpConnectionPool[cacheKey]->addSslOptions(request->getSslOptions());
httpConnectionPool[cacheKey]->pinCertificate(request->sslFingerprint);
Expand Down Expand Up @@ -101,15 +99,13 @@ HashMap<String, HttpConnection*> HttpClient::httpConnectionPool;
HashMap<String, RequestQueue*> HttpClient::queue;

#ifdef ENABLE_SSL
HashMap<String, SSLSessionId*> HttpClient::sslSessionIdPool;
HashMap<String, SslSessionId*> HttpClient::sslSessionIdPool;

void HttpClient::freeSslSessionPool()
{
for(int i = 0; i < sslSessionIdPool.count(); i++) {
for(unsigned i = 0; i < sslSessionIdPool.count(); i++) {
String key = sslSessionIdPool.keyAt(i);
free(sslSessionIdPool[key]->value);
sslSessionIdPool[key]->value = NULL;
free(sslSessionIdPool[key]);
delete sslSessionIdPool[key];
sslSessionIdPool[key] = NULL;
}
sslSessionIdPool.clear();
Expand Down
4 changes: 2 additions & 2 deletions Sming/SmingCore/Network/HttpClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ class HttpClient
static HashMap<String, RequestQueue*> queue;

#ifdef ENABLE_SSL
static HashMap<String, SSLSessionId*> sslSessionIdPool;
static HashMap<String, SslSessionId*> sslSessionIdPool;
#endif
};

/** @} */
#endif /* _SMING_CORE_NETWORK_HTTPCLIENT_H_ */
#endif /* _SMING_CORE_NETWORK_HTTPCLIENT_H_ */
28 changes: 28 additions & 0 deletions Sming/SmingCore/Network/Ssl/SslFingerprints.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/

#include "ssl/ssl.h"

enum SslFingerprintType {
eSFT_CertSha1 = 0, // << Fingerprint based on the SHA1 value of the certificate.
// Every time a certificate is renewed this value will change.
eSFT_PkSha256, // << Fingerprint based on the SHA256 value of the public key subject in the certificate.
// Only when the private key used to generate the certificate is used then that fingerprint
};

typedef struct {
uint8_t* certSha1 = nullptr; // << certificate SHA1 fingerprint
uint8_t* pkSha256 = nullptr; // << public key SHA256 fingerprint

void free()
{
delete certSha1;
certSha1 = nullptr;
delete pkSha256;
pkSha256 = nullptr;
}
} SslFingerprints;
112 changes: 112 additions & 0 deletions Sming/SmingCore/Network/Ssl/SslKeyCertPair.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/

#ifndef SMINGCORE_NETWORK_SSLKEYCERTPAIR_H_
#define SMINGCORE_NETWORK_SSLKEYCERTPAIR_H_

#include "ssl/ssl.h"
#include "WString.h"

/** @brief Class to manage an SSL key certificate with optional password
*/
class SslKeyCertPair
{
public:
bool isValid()
{
return key && certificate;
}

/** @brief Create certificate using provided values
* @param newKey
* @param newKeyLength
* @param newCertificate
* @param newCertificateLength
* @param newKeyPassword
* @retval bool false on memory allocation failure
* @note We take a new copy of the certificate
*/
bool assign(const uint8_t* newKey, unsigned newKeyLength, const uint8_t* newCertificate,
unsigned newCertificateLength, const char* newKeyPassword = nullptr)
{
free();

if(newKeyLength != 0 && newKey != nullptr) {
if(!key.setLength(newKeyLength)) {
return false;
}
memcpy(key.begin(), newKey, newKeyLength);
}

if(newCertificateLength != 0 && newCertificate != nullptr) {
if(!certificate.setLength(newCertificateLength)) {
return false;
}
memcpy(certificate.begin(), newCertificate, newCertificateLength);
}

unsigned passwordLength = (newKeyPassword == nullptr) ? 0 : strlen(newKeyPassword);
if(passwordLength != 0) {
keyPassword.setString(newKeyPassword, passwordLength);
if(!keyPassword) {
return false;
}
}

return true;
}

/** @brief Assign another certificate to this structure
* @param keyCert
* @retval bool false on memory allocation failure
* @note We take a new copy of the certificate
*/
bool assign(const SslKeyCertPair& keyCert)
{
*this = keyCert;
return (key == keyCert.key) && (keyPassword == keyCert.keyPassword) && (certificate == keyCert.certificate);
}

void free()
{
key = nullptr;
keyPassword = nullptr;
certificate = nullptr;
}

const uint8_t* getKey()
{
return reinterpret_cast<const uint8_t*>(key.c_str());
}

unsigned getKeyLength()
{
return key.length();
}

const char* getKeyPassword()
{
return keyPassword.c_str();
}

const uint8_t* getCertificate()
{
return reinterpret_cast<const uint8_t*>(certificate.c_str());
}

unsigned getCertificateLength()
{
return certificate.length();
}

private:
String key;
String keyPassword;
String certificate;
};

#endif /* SMINGCORE_NETWORK_SSLKEYCERTPAIR_H_ */
49 changes: 49 additions & 0 deletions Sming/SmingCore/Network/Ssl/SslSessionId.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/

#ifndef SMINGCORE_NETWORK_SSLSESSIONID_H_
#define SMINGCORE_NETWORK_SSLSESSIONID_H_

#include "ssl/ssl.h"
#include "WString.h"

/** @brief Manages buffer to store SSL Session ID
*/
class SslSessionId
{
public:
/** @brief May be called even when object is null */
const uint8_t* getValue()
{
return this ? reinterpret_cast<const uint8_t*>(value.c_str()) : nullptr;
}

/** @brief May be called even when object is null */
unsigned getLength()
{
return this ? value.length() : 0;
}

bool isValid()
{
return getLength() != 0;
}

bool assign(const uint8_t* newValue, unsigned newLength)
{
if(!value.setLength(newLength)) {
return false;
}
memcpy(value.begin(), newValue, newLength);
return true;
}

private:
String value;
};

#endif /* SMINGCORE_NETWORK_SSLSESSIONID_H_ */
22 changes: 22 additions & 0 deletions Sming/SmingCore/Network/Ssl/SslStructs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
****/

#ifndef SMINGCORE_NETWORK_SSL_SSLSTRUCTS_H_
#define SMINGCORE_NETWORK_SSL_SSLSTRUCTS_H_

#include "SslFingerprints.h"
#include "SslKeyCertPair.h"
#include "SslSessionId.h"

/*
* These structures have been renamed, please use the revised convention SslXXX
*/
typedef SslKeyCertPair SSLKeyCertPair __attribute__((deprecated));
typedef SslSessionId SSLSessionId __attribute__((deprecated));
typedef SslFingerprints SSLFingerprints __attribute__((deprecated));

#endif /* SMINGCORE_NETWORK_SSL_SSLSTRUCTS_H_ */
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Sming/SmingCore/Network/TcpClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ bool TcpClient::pinCertificate(const uint8_t* fingerprint, SslFingerprintType ty
return true;
}

bool TcpClient::pinCertificate(const SSLFingerprints& fingerprints)
bool TcpClient::pinCertificate(const SslFingerprints& fingerprints)
{
bool success = false;
if(fingerprints.certSha1 != nullptr) {
Expand Down
12 changes: 6 additions & 6 deletions Sming/SmingCore/Network/TcpClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "Delegate.h"

#ifdef ENABLE_SSL
#include "SslValidator.h"
#include "Ssl/SslValidator.h"
#endif

class TcpClient;
Expand Down Expand Up @@ -154,15 +154,15 @@ class TcpClient : public TcpConnection
bool pinCertificate(const uint8_t* fingerprint, SslFingerprintType type);

/**
* @brief Requires(pins) the remote SSL certificate to match certain fingerprints
* @brief Requires(pins) the remote SSL certificate to match certain fingerprints
*
* @note The data inside the fingerprints parameter is passed by reference
* @note The data inside the fingerprints parameter is passed by reference
*
* @param SSLFingerprints - passes the certificate fingerprints by reference.
* @param fingerprints - passes the certificate fingerprints by reference.
*
* @return bool true of success, false or failure
* @retval bool true of success, false or failure
*/
bool pinCertificate(const SSLFingerprints& fingerprints);
bool pinCertificate(const SslFingerprints& fingerprints);
#endif

protected:
Expand Down
Loading

0 comments on commit 88a080b

Please sign in to comment.