Hey Moriarty,
On Thu, Mar 10, 2016 at 11:35:01PM -0800, moriarty wrote:
> I'll work on publishing the changes, and if that doesn't take long, can
> take a look at storing .rodata in ROM
How'd you get on with this?
> the documentation - uxTaskGetStackHigh*WaterMark* measures *watermark* (what
> a surprise!), not the current stack usage. So, it's monotonically growing
> by default.
This is true, but it should still hit a maximum point after a while, or something has gone wrong... :)
> Bad news: memory is tight. After the MQTT connection is established,
> there's only 6k heap left (on the bright side, there's plenty of stack
> available - the task was configured with stack size of 2100 variables), and
> the stack watermark is just ~400 (yeah, that's pretty close).
>
> And it took a few kinky hacks to get even to this tight state:
> 1) bigint library used by mbedtls (unfortunately) follows the best
> security practices and zeroes all the dynamic memory it uses before and
> *after* usage. This means they only use malloc() + free() pair and never
> realloc(). At the same time, they grow their memory regions quite often,
> and that leads to fragmentation and excessive heap usage. One of the
> changes I made was to use realloc(). This is a big no-no in a secure code.
> I'll think what we can do here without sacrificing security, and try to
> push a change to mbedtls.
Hmm. :( Do you have any numbers on how fragmented the heap gets?
Having a glance at the bignum implementation, maybe we can add some tweaks to preemptively allocate larger buffers to avoid growing unnecessarily? If it dramatically reduces the amount of fragmentation then it might be something the mbedtls maintainers would accept upstream as well.
> 2) mbedtls parameters had to be tweaked, most
> notably MBEDTLS_SSL_MAX_CONTENT_LEN was decreased (also disabled everything
> except TLS 1.2, but I don't think that impacted memory usage
> significantly). This is more or less fine by itself, but there's no
> guarantee that the library will still work with other servers configured
> differently. Even more, I think if Amazon change their server's
> configuration (maybe add more cyphers), there's a chance the library could
> stop working. OTOH, I'm no expert here and these are just speculations
MBEDTLS_SSL_MAX_CONTENT_LEN was already too low to be spec compliant. :( The spec says you have to accept up to 16KiB of data in a single "block", unless you negotiate a smaler buffer size using the TLS content length extension. Which most servers don't enable :(.
Connecting to a server which doesn't support session size negotiation is playing with fire, because at any point they can send you a block that you can't decrypt (because it's too long) and then you have no choice but to close the session. However if you know a bit about the application layer then you may be able to be sure that the largest plaintext sent at once is X bytes, in which case you can round up to the cipher block size (I think?) and then you're OK...
The big change I'd like to make in mbedtls (and submit back upstream) is to allow asymetrical MBEDTLS_SSL_MAX_CONTENT_LEN. Because even though you may not know how large the longest block you receive might be, you can certainly control the largest block you send. So I think having a 512 byte TLS transmit buffer is fine (if a bit less efficient on the wire), and that gives you more space to allocate for the receive buffer.
I can't think of a reason the mbedtls maintainers won't accept that patch, although I'm not a cryptography expert so maybe it weakens the encryption somehow (I just can't see how...)
Angus