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

Improve memory management of SSL fingerprint data #1618

Merged
merged 6 commits into from
Feb 14, 2019

Conversation

mikee47
Copy link
Contributor

@mikee47 mikee47 commented Feb 12, 2019

Uses may now use methods of SslLFingerprints to provide certificate data. I've updated the Basic_Ssl and HttpClient sample applications accordingly.

Add methods to SslFingerprints structure to manage allocation/de-allocation of fingerprint data.
Create SslValidatorList class for TcpClient and move relevant code into methods.
Take care to set SslFingerprints members to nullptr when ownership relinquished - previous code TcpClient::pinCertificate().
bugfix: In TcpClient::onSslConnected, the first matching validator causes checking to stop, which means the validator dataj for any subsequent fingerprints never gets released. This is fixed in the new SslValidatorList implementation.
Revise Basic_Ssl sample to use different web-page with fingerprint that doesn't change.
Also change HardwareSerial to base on ReadWriteStream instead of Stream, allows incoming data to be streamed direct.

@mikee47
Copy link
Contributor Author

mikee47 commented Feb 12, 2019

This is more-or-less just be a re-factoring of existing code without changing the validation mechanism. However, it feels to me like an overly complex way to crack what should be a fairly simple problem.

The user's application passes their fingerprints to HttpRequest, which keeps them as an SslFingerprints structure. They are then passed into TcpClient, which pulls the values out into a hashmap. Validation eventually happens in TcpClient::onSslConnected. This is essentially a 'one-time fingerprint cache'; the mechanism could be more simply implemented wrapping everything in the SslValdation class, then passing that around.

Alternatively, we could bypass all of this by just using a callback (to the user's application instead...

Thoughts / comments?

Add methods to SSLFingerprints structure to manage allocation/de-allocation of fingerprint data.
Create `SSLValidatorList` class for `TCPClient` and move relevant code into methods.

Take care to set `SSLFingerprints` members to `nullptr` when ownership relinquished (see `TcpClient::pinCertificate()`)

bugfix: In `TcpClient::onSslConnected`, the first matching validator causes checking to stop, which means the validator dataj for any subsequent fingerprints never gets released. This is fixed in the `SSLValidatorList` destructor.
…that doesn't change.

Add length checks to SslFingerprints.
Also change `HardwareSerial` to base on `ReadWriteStream` instead of `Stream`, allows incoming data to be streamed direct.
@mikee47 mikee47 force-pushed the fix/SSL_Fingerprints branch from 5c5d885 to 6d992fe Compare February 12, 2019 18:14
@mikee47
Copy link
Contributor Author

mikee47 commented Feb 13, 2019

@slaff As I've started using __attribute__((deprecated)) I can prepare a PR for all the remaining items which only have @deprecated comment.

Another similar general change was use of override.

Both of these I think should be introduced sooner rather than later...

Sming/SmingCore/Network/Ssl/SslFingerprints.h Outdated Show resolved Hide resolved
Sming/SmingCore/Network/Ssl/SslFingerprints.h Outdated Show resolved Hide resolved
Sming/SmingCore/Network/Ssl/SslValidator.h Show resolved Hide resolved
Sming/SmingCore/Network/Ssl/SslValidator.h Outdated Show resolved Hide resolved
@slaff
Copy link
Contributor

slaff commented Feb 13, 2019

@slaff As I've started using __attribute__((deprecated)) I can prepare a PR for all the remaining items which only have @deprecated comment.
Another similar general change was use of override.

Yes, please. Make sure also to modify the https://github.com/SmingHub/Sming/wiki/Coding-Style-Rules wiki page to reflect those changes.

// request->->pinCertificate(sha1Fingerprint, eSFT_CertSha1)
fingerprints.setSha1_P(sha1Fingerprint, sizeof(sha1Fingerprint));

// request->pinCertificate(fingerprints);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe I am missing something but where are the fingerprints attached to the request?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the commented-out line - so behaviour isn't changed. Can un-comment if you prefer, or re-comment fingerprints.setXXX lines?

Copy link
Contributor

Choose a reason for hiding this comment

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

Uncomment and change the comments text if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I'll also update the fingerprints (they've changed)

* @param fingerprints - passes the certificate fingerprints by reference.
*
* @retval bool true of success, false or failure
* @retval bool true of success, false or failure
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change this also to 'bool true on success, false on failure' ?

Sming/SmingCore/Network/Ssl/SslValidator.h Show resolved Hide resolved
*/
bool setSha1_P(const uint8_t* cert, unsigned length)
{
// Word-aligned and sized buffers don't need special handling
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the word-aligning planned to be added here? If not then this method is identical to the non _P versions and my question is why is that needed?

Copy link
Contributor Author

@mikee47 mikee47 Feb 13, 2019

Choose a reason for hiding this comment

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

It's a matter of semantics; it also means we could add an optimisation internally which avoids copying the fingerprint data but instead takes a reference to it. I can do that if you want to stick with this model, but I'd also change to a class and make the certificate data private, which would break existing user's code...

Copy link
Contributor

Choose a reason for hiding this comment

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

but I'd also change to a class and make the certificate data private, which would break existing user's code...

Let's leave this change for now and schedule it for the next version.

@@ -19,6 +19,7 @@
enum StreamType {
eSST_Invalid, ///< Stream content not valid
eSST_Memory, ///< Memory data stream
eSST_Serial, ///< Serial port
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm... Do we need those specific types or more general ones would be better?

Copy link
Contributor Author

@mikee47 mikee47 Feb 13, 2019

Choose a reason for hiding this comment

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

I do wonder if we need StreamType at all? In the framework it's barely used:

IDataSourceStream::isValid()

Inherited classes can just override this method directly, rather than returning eSST_Invalid from getStreamType()

HttpRequest::getBody() and HttpResponse::getBody()

Both of these fail if the stream type isn't eSST_Memory, but I'm not sure that check is even necessary.

So we could fix these points and deprecate the getStreamType() method completely. We change IDataSourceStream::getStreamType() to return eSST_Unknown and remove it from HardwareSerial.

Copy link
Contributor

Choose a reason for hiding this comment

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

So we could fix these points and deprecate the getStreamType() method completely. We change IDataSourceStream::getStreamType() to return eSST_Unknown and can then omit it from HardwareSerial completely.

That sounds good to me. Just make sure that it is in a separate PR.

@slaff slaff added this to the 3.7.2 milestone Feb 13, 2019
* Additional checks in `SslFingerprints` assignment operators
* Output debug error if `SslFingerprint::setXXX` fails
* Update fingerprints in `HttpClient` sample and enable checking
Validator callback still responsible for de-allocating memory, but can be called with ssl = nullptr
@mikee47 mikee47 force-pushed the fix/SSL_Fingerprints branch 4 times, most recently from 44f5848 to 16732c4 Compare February 13, 2019 14:15
Move SslFingerprint code out of header
Add check for flash memory in `SslFingerprint::setValue`
@mikee47 mikee47 force-pushed the fix/SSL_Fingerprints branch from 33e3780 to ed1ce28 Compare February 13, 2019 21:45
@mikee47
Copy link
Contributor Author

mikee47 commented Feb 13, 2019

OK, I've tested this last commit with various dodgy keys and behaves predictably. Users should be able to throw any old crap in there and it'll play nice.

@slaff slaff removed the 3 - Review label Feb 14, 2019
@slaff slaff merged commit cbed639 into SmingHub:develop Feb 14, 2019
@mikee47 mikee47 deleted the fix/SSL_Fingerprints branch February 14, 2019 14:03
@slaff slaff mentioned this pull request Feb 27, 2019
4 tasks
mikee47 added a commit to mikee47/Sming that referenced this pull request Jun 12, 2019
* SmingHub#1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`
mikee47 added a commit to mikee47/Sming that referenced this pull request Jun 12, 2019
* SmingHub#1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`
mikee47 added a commit to mikee47/Sming that referenced this pull request Jun 12, 2019
* SmingHub#1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`
mikee47 added a commit to mikee47/Sming that referenced this pull request Jun 16, 2019
* SmingHub#1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`
mikee47 added a commit to mikee47/Sming that referenced this pull request Jun 16, 2019
* SmingHub#1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`
slaff pushed a commit that referenced this pull request Jun 16, 2019
* Add additional checks to `Vector` class methods

* #1618 (comment)
* Change `ensureCapacity` to adjust new capacity by `increment`, thus simplifying code which uses it
* Add `bool` return value to:
	`addElement()` - so that `add()` return value isn't meaningless
	`ensureCapacity()`
	`setSize()`
	`insertElementAt()`
	`setElementAt()`

* Apply coding style and fix use of parentheses
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.

2 participants