-
Notifications
You must be signed in to change notification settings - Fork 833
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
stunnel 5.61 support #4807
stunnel 5.61 support #4807
Conversation
083c95f
to
6874a8d
Compare
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.
Great work. A few minor items to review.
src/ssl.c
Outdated
*pkcs12 = NULL; | ||
if (mem != NULL && localPkcs12 != NULL) { | ||
if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { | ||
ret = wc_d2i_PKCS12(mem, memSz, localPkcs12); |
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.
src/ssl.c:63445:38: error: implicit conversion loses integer precision: 'long' to 'word32' (aka 'unsigned int') [-Werror,-Wshorten-64-to-32]
ret = wc_d2i_PKCS12(mem, memSz, localPkcs12);
~~~~~~~~~~~~~ ^~~~~
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.
Fixed as part of the Jenkins fixes.
Also need to add new session fields to i2d and d2i api. |
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 think there is great work in this PR, but we need to be very careful about how this will impact our customers... memory use, locking performance, API compatibility, etc...
Will you look into the resume test failures? Thanks
src/ssl.c
Outdated
@@ -12459,7 +12460,7 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) | |||
{ | |||
WOLFSSL_ENTER("SSL_get_session"); | |||
if (ssl) | |||
return wolfSSL_GetSession(ssl, NULL, 1); | |||
return &ssl->session; |
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.
This doesn't work. wolfSSL_get_session
is called... WOLFSSL object can be free'd between resumption.
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.
That is correct because wolfSSL_get_session
should return a reference to the working session (that is what SSL_get_session
does). Users who want to retain a copy of the session should always use wolfSSL_get1_session
as that will guarantee either an incremented refCount of a duplicated object.
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.
This will break existing compatibility. Did you consider making the WOLFSSL_SESSION in WOLFSSL a pointer and allocating from heap? It would not increase memory use, since the WOLFSSL object is already allocated from the heap.
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.
This will break existing compatibility.
While true, the assumption is that a pointer directly to the cache entry is just as unsafe. The client user has no way of knowing if the session didn't change before setting it in a new SSL object. We could make wolfSSL_get_session
and wolfSSL_get1_session
do the same thing but that will cause leaks since wolfSSL_get_session
is meant to return a reference to the SSL object's working session.
Did you consider making the WOLFSSL_SESSION in WOLFSSL a pointer and allocating from heap?
This is an interesting idea. It should be fairly easy to do. The only issue would be that the heap is further fragmented. Do you think I should pursue this direction?
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.
Yes please. You'll have to track that the allocated WOLFSSL_SESSION was retrieved and assume to not free it on wolfSSL_free
. I think the session_ref stuff already does something similar, which could all be cleaned up and combined.
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.
Do you mean that the session should point into the cache? I was thinking it would be allocated on wolfSSL_new and free'd on wolfSSL_free. A user could retain the object by either calling wolfSSL_get1_session or the up_ref API.
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.
No, allocated.
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.
Got it. I'll try to get it done tomorrow.
Out of these three, I think API compatibility is the only concern. Memory use will not be increased because |
e007ecc
to
794fe43
Compare
794fe43
to
58ff372
Compare
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.
Great work on this! Lots to review here. First pass feedback.
@@ -6683,10 +6683,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) | |||
void FreeArrays(WOLFSSL* ssl, int keep) | |||
{ | |||
if (ssl->arrays) { | |||
if (keep) { | |||
if (keep && !IsAtLeastTLSv1_3(ssl->version)) { |
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.
Since ssl->session
is a pointer now, please also add NULL check before trying to touch it.
@@ -8983,7 +8972,8 @@ static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) | |||
return -1; | |||
|
|||
case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ | |||
if (ssl->ctx->autoRetry) | |||
if (ssl->ctx->autoRetry && !ssl->options.handShakeDone && |
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.
Good fix here... This is probably one that needs to be merged soon.
src/internal.c
Outdated
@@ -20201,7 +20193,11 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) | |||
return "wrong client/server type"; | |||
|
|||
case NO_PEER_CERT : | |||
#ifndef OPENSSL_EXTRA |
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 is fine with me if you change NO_PEER_CERT
and BAD_BINDER
for all build cases (not just OPENSSL_EXTRA). But consider adding comment that openssl compatibility expects this specific text.
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.
One fixed value with comment to explain compatibility.
src/internal.c
Outdated
@@ -29955,6 +29942,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, | |||
#endif | |||
|
|||
ret = MatchSuite(ssl, &clSuites); | |||
#ifdef OPENSSL_EXTRA | |||
/* Give user last chance to provide a cert for cipher selection */ |
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.
This section is a very good change. If someone has setup a certificate callback with wolfSSL_CTX_set_cert_cb
then they have the option to load different certificate and the call below to try MatchSuite
again will adjust.
I'd prefer this logic to be cleaned up and only called if ssl->ctx->certSetupCb
is set. I do realize it is also checked in CertSetupCbWrapper
, but the return code logic from it doesn't report error for it. I want to make sure a future change doesn't cause an issue here.
Also does ret = MatchSuite(ssl, &clSuites);
above at 29944 still need called before or would it make sense to just always call after the CertSetupCbWrapper
?
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 was thinking that the callback could be dependent on the cipher chosen but that doesn't make sense since the certificate selection will heavily influence the ciphersuite. Changing to one call after the cert callback.
@@ -30513,6 +30504,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, | |||
#ifdef WOLFSSL_EARLY_DATA | |||
word32 maxEarlyDataSz; /* Max size of early data */ | |||
#endif | |||
#endif | |||
#ifdef WOLFSSL_TICKET_HAVE_ID | |||
byte id[ID_LEN]; |
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.
Added 32 bytes here should be fine, since the total ticket size is still under the SESSION_TICKET_LEN=256
default.
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 do you think this should be added permanently for all configurations with the session cache enabled?
src/internal.c
Outdated
XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); | ||
ssl->session.ticket = ssl->session._staticTicket; | ||
ssl->session.ticketLenAlloc = 0; | ||
if (ssl->session->ticketLenAlloc > 0) { |
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.
Please add a ssl->session != NULL
check to this function. I simulated free'ing the ssl->session in FreeHandshakeResources as a test...
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.
The ssl->session
member is allocated when the WOLFSSL
object is created and free
'ed only on wolfSSL_free
. It is used extensively everywhere. Other members aren't tested for either like ssl->arrays
or ssl->suites
. I'm not sure if this is really necessary. Are you sure?
$ grep -r -P --include='*.[ch]' '\-\>session\-\>' | wc -l
233
ssl->session.cipherSuite = ssl->options.cipherSuite; | ||
ssl->session.ticketSeen = now; | ||
ssl->session.ticketAdd = ageAdd; | ||
ssl->session->timeout = lifetime; |
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.
Same.. please add an ssl->session != NULL
check in DoTls13NewSessionTicket
session->sessionIDSz = ID_LEN; | ||
(void)error; | ||
|
||
WOLFSSL_ENTER("AddSession"); |
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.
Please add check for ssl->session == NULL
.
58ff372
to
2ee15ea
Compare
13d17c6
to
d01baed
Compare
Jenkins failure due to aborted test. |
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.
Lots of excellent work in this PR and looking forward to getting it merged. Just a few minor feedback items.
test_wolfSSL_CTX_add_session_server_ctx == NULL) { | ||
AssertNotNull(test_wolfSSL_CTX_add_session_server_ctx | ||
= wolfSSL_get_SSL_CTX(ssl)); | ||
AssertIntEQ(wolfSSL_CTX_up_ref(wolfSSL_get_SSL_CTX(ssl)), |
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.
Building with ./configure CFLAGS="-DWOLFSSL_TICKET_HAVE_ID -DHAVE_EXT_CACHE" && make
gives error because wolfSSL_CTX_up_ref
is not available. You might consider making that API public when session cache is enabled, not just on compatibility layer?
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 made wolfSSL_CTX_up_ref
always available. As I explain in the commit message:
wolfSSL_CTX_up_ref
is a small and potentially useful API for users so it doesn't need to be restricted only to the compatibility layer. The reference counting mechanisms are always available anyway. This just exposes the functionality to the user.
- New/Implemented API - `SSL_has_pending` - `wolfSSL_CertManagerLoadCRLFile` - `wolfSSL_LoadCRLFile` - `wolfSSL_CTX_LoadCRLFile` - `wolfSSL_CTX_add_session` - Calling chain certificate API (for example `wolfSSL_CTX_use_certificate_chain_file`) no longer requires an actual chain certificate PEM file to be passed in as input. `ProcessUserChain` error in `ProcessBuffer` is ignored if it returns that it didn't find a chain. - Add `WOLFSSL_TICKET_HAVE_ID` macro. When defined tickets will include the original session ID that can be used to lookup the session in internal cache. This is useful for fetching information about the peer that doesn't get sent in a resumption (such as the peer's certificate chain). - Add `ssl->ticketSessionID` field because `ssl->session.sessionID` is used to return the "bogus" session ID sent by the client in TLS 1.3 - `OPENSSL_COMPATIBLE_DEFAULTS` changes - Define `WOLFSSL_TRUST_PEER_CERT` and certificates added as CA's will also be loaded as trusted peer certificates - Define `WOLFSSL_TLS13_MIDDLEBOX_COMPAT` - Seperate `internalCacheOff` and `internalCacheLookupOff` options to govern session addition and lookup - `VerifyServerSuite` now determines if RSA is available by checking for it directly and not assuming it as the default if static ECC is not available - `WOLFSSL_SESSION` changes - `ssl->extSession` added to return a dynamic session when internalCacheOff is set - `ssl->session.refPtr` made dynamic and gets free'd in `SSL_ResourceFree` - If `SSL_MODE_AUTO_RETRY` is set then retry should only occur during a handshake - `WOLFSSL_TRUST_PEER_CERT` code now always uses `cert->subjectHash` for the `cm->tpTable` table row selection - Change some error message names to line up with OpenSSL equivalents - Run `MatchSuite` again if certificate setup callback installed and successful - Refactor clearing `ASN_NO_PEM_HEADER` off the error queue into a macro - `wolfSSL_get_peer_certificate` now returns a duplicated object meaning that the caller needs to free the returned object - Allign `wolfSSL_CRYPTO_set_mem_functions` callbacks with OpenSSL API - `wolfSSL_d2i_PKCS12_bio` now consumes the input BIO. It now supports all supported BIO's instead of only memory BIO. - stunnel specific - Always return a session object even if we don't have a session in cache. This allows stunnel to save information in the session external data that will be transfered to new connections if the session is reused - When allocating a dynamic session, always do `wolfSSL_SESSION_set_ex_data(session, 0, (void *)(-1)`. This is to mimic the new index callback set in `SSL_SESSION_get_ex_new_index`. - Fix comment in `wolfSSL_AES_cbc_encrypt` - Trusted peer certificate suite tests need to have CRL disabled since we don't have the issuer certificate in the CA store if the certificates are only added as trusted peer certificates. tested
- Adding and getting sessions to and from the local cache is now atomic. - The new internal `wolfSSL_GetSessionFromCache` requires a destination object to be supplied when retrieving from the cache so that items can be retrieved independently from the cache. For most existing calls, the destination is `ssl->session`. -`PREALLOC_SESSION_TICKET_LEN` defines how much memory is temporarily allocated for the ticket if it doesn't fit in the static session buffer.
- Refactor session cache access into `AddSessionToCache` and `wolfSSL_GetSessionFromCache`
- Move test to `HAVE_IO_TESTS_DEPENDENCIES` - Implement `wolfSSL_trust_peer_cert` - have{cipher} options weren't being set with only RSA enabled
Before this pull request, `wolfSSL_get_session` always returned a pointer to the internal session cache. The user can't tell if the underlying session hasn't changed before it calls `wolfSSL_set_session` on it. This PR adds a define `NO_SESSION_CACHE_REF` (for now only defined with `OPENSSL_COMPATIBLE_DEFAULTS`) that makes wolfSSL only return a pointer to `ssl->session`. The issue is that this makes the pointer returned non-persistent ie: it gets free'd with the `WOLFSSL` object. This commit leverages the lightweight `ClientCache` to "increase" the size of the session cache. The hash of the session ID is checked to make sure that the underlying session hasn't changed.
- Make `InternalTicket` memory alignment independent
`wolfSSL_CTX_up_ref` is a small and potentially useful API for users so it doesn't need to be restricted only to the compatibility layer. The reference counting mechanisms are always available anyway. This just exposes the functionality to the user.
4609207
to
fb943a2
Compare
Reported in ZD13606
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.
Big changes! Session support massive refactor.
* Adds stateful handling of DH shared secret computation in `SetupKeys`. * Improved the decrypt handling to use internal functions and avoid generating alerts on failures. * Fix for sniffer resume due to missing `sessionIDSz` broken in wolfSSL#4807. * Fix sniffer test cases to split resume (session_ticket) tests. * Add `snifftest` list of build features so test script can gate running resume test.
* Adds stateful handling of DH shared secret computation in `SetupKeys`. * Improved the decrypt handling to use internal functions and avoid generating alerts on failures. * Fix for sniffer resume due to missing `sessionIDSz` broken in wolfSSL#4807. * Fix sniffer test cases to split resume (session_ticket) tests. * Add `snifftest` list of build features so test script can gate running resume test.
SSL_has_pending
wolfSSL_CertManagerLoadCRLFile
wolfSSL_LoadCRLFile
wolfSSL_CTX_LoadCRLFile
wolfSSL_CTX_add_session
wolfSSL_GetSessionFromCache
requires a destination object to be supplied when retrieving from the cache so that items can be retrieved independently from the cache. For most existing calls, the destination isssl->session
.PREALLOC_SESSION_TICKET_LEN
defines how much memory is temporarily allocated for the ticket if it doesn't fit in the static session buffer.wolfSSL_get_session
always returned a pointer to the internal session cache. The user can't tell if the underlying session hasn't changed before it callswolfSSL_set_session
on it. This PR adds a defineNO_SESSION_CACHE_REF
(for now only defined withOPENSSL_COMPATIBLE_DEFAULTS
) that makes wolfSSL only return a pointer tossl->session
. The issue is that this makes the pointer returned non-persistent ie: it gets free'd with theWOLFSSL
object. This pull request leverages the lightweightClientCache
to "increase" the size of the session cache. The hash of the session ID is checked to make sure that the underlying session hasn't changed.wolfSSL_CTX_use_certificate_chain_file
) no longer requires an actual chain certificate PEM file to be passed in as input.ProcessUserChain
error inProcessBuffer
is ignored if it returns that it didn't find a chain.WOLFSSL_TICKET_HAVE_ID
macro. When defined tickets will include the original session ID that can be used to lookup the session in internal cache. This is useful for fetching information about the peer that doesn't get sent in a resumption (such as the peer's certificate chain).ssl->session->altSessionID
field becausessl->session.sessionID
is used to return the "bogus" session ID sent by the client in TLS 1.3 and when using tickets in TLS <= 1.2OPENSSL_COMPATIBLE_DEFAULTS
changesWOLFSSL_TRUST_PEER_CERT
and certificates added as CA's will also be loaded as trusted peer certificatesinternalCacheOff
andinternalCacheLookupOff
options to govern session addition and lookupVerifyServerSuite
now determines if RSA is available by checking for it directly and not assuming it as the default if static ECC is not availableWOLFSSL_SESSION
changesssl->session->altSessionID
added to return a dynamic session when internalCacheOff is setssl->session.refPtr
removed in favor of makingssl->session
a seperate heap allocated object that can be returned to the userSSL_MODE_AUTO_RETRY
is set then retry should only occur during a handshake with a limitWOLFSSL_TRUST_PEER_CERT
code now always usescert->subjectHash
for thecm->tpTable
table row selectionMatchSuite
ASN_NO_PEM_HEADER
off the error queue into a macrowolfSSL_get_peer_certificate
now returns a duplicated object meaning that the caller needs to free the returned objectwolfSSL_CRYPTO_set_mem_functions
callbacks with OpenSSL APIwolfSSL_d2i_PKCS12_bio
now consumes the input BIO. It now supports all supported BIO's instead of only memory BIO.wolfSSL_SESSION_set_ex_data(session, 0, (void *)(-1)
. This is to mimic the new index callback set inSSL_SESSION_get_ex_new_index
.wolfSSL_AES_cbc_encrypt