I'd like to minimize the amount of RAM that is required by CyaSSL client - hopefully to less than 28KB. Do you think this is possible?
I am compiling in a non-standard environment, and am therefore using #defines to control how Cyassl compiles. Here are the current #defines that I am using:
#define SIZEOF_LONG_LONG 8
Maybe there are other compile options that I should try? The big memory hog seems to be the SSL structure - I cannot seem to get it below 40688 bytes in CyaSSL 1.5.4.
I saw a suggestion in another form post of using dynamic buffers for the input / output streams. It seems like this wouldn't necessarily guarantee a smaller memory footprint (it would still be possible for CyaSSL to be attempting to receive/send 16K, in which case the same amount of memory would be required, right?). Maybe there is a way to make CyaSSL use the same input and output buffer?
Any thoughts that you have will be greatly appreciated. Thank you,
You're right nearly all of the memory is from the in/out buffers, 18,953 each.
CyaSSL used to only use dynamic memory but at the request of users and for speedup static buffers were used instead.
If you control both ends, or know for sure the max size of each record you will face, you can lower the buffer size by playing with
#define BUFFER16K_LEN RECORD_HEADER_SZ + MAX_RECORD_SIZE + \
MAX_COMP_EXTRA + MAX_MTU + MAX_MSG_EXTRA
Which reminds me, MAX_COMP_EXTRA is only used if compression is built in and MAX_MTU is really only used if sniffer mode is being used. That define needs to change to reflect that, you can remove both and save yourself 5k right there. 2 x (1,000 + 1,500).
Now RECORD_HEADER_SZ and MAX_MSG_EXTRA (padding + MAC) should stay as they are but that's only 73 bytes.
But you can lower MAX_RECORD_SIZE if you're not doing bulk data transfer, it's currently 16,384, the max raw data length of each SSL record.
CyaSSL could be changed to only use one buffer for both input and output though it's not set up that way right now. Each buffer makes slightly different assumptions about itself and logic would need to be added to make sure each buffer is emptied before trying to use the other. For example, the client receives 10K from the server, but reads in 5k chunks and wishes to respond after reading the first chunk. Not easily possible with only one buffer.
I think it might be best to abstract the input / output buffers. Make each a pointer that can point to a static buffer depending on build options, can share a buffer depending on build options, or even let the user control the buffer (not sure how much at this point). Any other ideas? What do you think?
Thank you for all of your insight!
I like your idea of abstracting the input / output buffers and having build options to allow the user to have some control - I think this would give CyaSSL a lot more portability to memory constrained systems if the user could somehow implement the input / output buffers in serial RAM.
My max record size is 1K. However, I am not sure how large MAX_RECORD_SIZE needs to be to complete the SSL handshake (certificates and key exchange, etc). Do you have any thoughts on this? Do you think I can get by with MAX_RECORD_SIZE of 4K?
It depends on the servers you're connecting to and the certificates they're sending during the handshake. If the max data record size is 1k the only SSL record that can be bigger than that is the certificate record, which could be infintely large split into 16k SSL records. But typically, 1 - 3 certificates are sent with an average of say 1,250 bytes. So while 4k is probably fine I'd recommend 6k or even 8k to be safe. That still saves you 16k (8k x 2 buffers) + 5k from the other defines above for a saving of 21k.
I'll post back after the buffer changes are made. Another idea occurred to me which is to have an option for small static buffers, configurable but defaulting to 1 or 2k, and then using dynamic memory when a larger record comes in for a certificate chain or a large data message. Does that work?
Great - thanks the advice. I think 8k buffers will be sufficiently small for me.
I like your latest idea best for the buffers. It seems that this will give the best of both worlds - high speed for packets < 1 or 2k, and much smaller memory usage in the event of a large packet so long as the send and receive buffers do not simultaneously need to be large. This would certainly work well for my application.
Log in to post a comment.