-
-
Notifications
You must be signed in to change notification settings - Fork 344
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
Conversation
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 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.
5c5d885
to
6d992fe
Compare
@slaff As I've started using Another similar general change was use of Both of these I think should be introduced sooner rather than later... |
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
Sming/SmingCore/Network/TcpClient.h
Outdated
* @param fingerprints - passes the certificate fingerprints by reference. | ||
* | ||
* @retval bool true of success, false or failure | ||
* @retval bool true of success, false or failure |
There was a problem hiding this comment.
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' ?
*/ | ||
bool setSha1_P(const uint8_t* cert, unsigned length) | ||
{ | ||
// Word-aligned and sized buffers don't need special handling |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
* 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
44f5848
to
16732c4
Compare
Move SslFingerprint code out of header Add check for flash memory in `SslFingerprint::setValue`
33e3780
to
ed1ce28
Compare
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. |
* 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()`
* 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()`
* 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()`
* 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()`
* 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()`
* 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
Uses may now use methods of
SslLFingerprints
to provide certificate data. I've updated theBasic_Ssl
andHttpClient
sample applications accordingly.Add methods to SslFingerprints structure to manage allocation/de-allocation of fingerprint data.
Create
SslValidatorList
class forTcpClient
and move relevant code into methods.Take care to set
SslFingerprints
members tonullptr
when ownership relinquished - previous codeTcpClient::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 newSslValidatorList
implementation.Revise
Basic_Ssl
sample to use different web-page with fingerprint that doesn't change.Also change
HardwareSerial
to base onReadWriteStream
instead ofStream
, allows incoming data to be streamed direct.