Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Hi All. I guess all my theories are bang on, as the entire framework was integrated seamlessly making use of the above "theories". Thanks a ton to everyone, and extra thanks to Viktor Thanks and Regards, Ajay On 10 Oct 2016 6:34 a.m., "Ajay Garg"wrote: > Thanks Michael for the reply. > > And yes, your points are absolutely valid. > > We do not assume anything at the client/server as such, we just read > the byte-streams, and generate (MQTT) packets out of bytestreams as > and when the starting- and ending- boundaries of a (new) MQTT-packet > are received. > > > Still, I believe all my 3 questions (step a, step b, and the 8-point > story in step c) are independent of this, and would like to hear from > you experts as to if my understanding of all those 3 steps is correct, > including the all important assumption > > *Implicit in this workflow is my assumption that SSL too builds up a > packet for every BIO_write done over "bio1". * > > I say it the most important, because our application is MQTT-based, > and all our communication is request/response based; we send a packet, > and expect an acknowledgement. > > In other words, if my implicit assumption is correct, then every > "BIO_write(bio1)" would generate a complete SSL-packet, which would be > available at "bio2" instantly and synchronously - ready to be > transferred over the wire. > > > Again, would be thankful from the bottom of my heart, to hear > confirmations/rejections regarding my theories in step a), step b) and > 8-point-story in step c) as per my previous email. > > > > Thanks and Regards, > Ajay > > On Mon, Oct 10, 2016 at 2:39 AM, Michael Wojcik > wrote: > >> From: openssl-users [mailto:openssl-users-boun...@openssl.org] On > Behalf > >> Of Ajay Garg > >> Sent: Sunday, October 09, 2016 14:12 > >> > >> Also, for all my cases, Nagle's algorithm has been disabled on the > >> client as well as the server, so every write (at client/server) > >> constitutes a packet-transferred. > > > > This assumption is incorrect. Nagle is not the only factor which > interferes with a 1-to-1 mapping between application sends and (IP) packets > on the wire. The peer's receive window, the interface and path MTUs, > fragmentation, transient network failures ... many things can either split > an application message into multiple IP packets or even multiple TCP > segments, or cause multiple application messages to be coalesced into a > single TCP segment (which usually is also a single IP packet, now that path > MTU determination usually works properly). > > > > You should never assume TCP is anything other than a byte-stream > service. An application that makes any assumptions about how its send > operations translate into TCP segments or IP packets is asking for trouble. > > > > -- > > Michael Wojcik > > Distinguished Engineer, Micro Focus > > > > > > > > -- > > openssl-users mailing list > > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users > > > > -- > Regards, > Ajay > -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Thanks Michael for the reply. And yes, your points are absolutely valid. We do not assume anything at the client/server as such, we just read the byte-streams, and generate (MQTT) packets out of bytestreams as and when the starting- and ending- boundaries of a (new) MQTT-packet are received. Still, I believe all my 3 questions (step a, step b, and the 8-point story in step c) are independent of this, and would like to hear from you experts as to if my understanding of all those 3 steps is correct, including the all important assumption *Implicit in this workflow is my assumption that SSL too builds up a packet for every BIO_write done over "bio1". * I say it the most important, because our application is MQTT-based, and all our communication is request/response based; we send a packet, and expect an acknowledgement. In other words, if my implicit assumption is correct, then every "BIO_write(bio1)" would generate a complete SSL-packet, which would be available at "bio2" instantly and synchronously - ready to be transferred over the wire. Again, would be thankful from the bottom of my heart, to hear confirmations/rejections regarding my theories in step a), step b) and 8-point-story in step c) as per my previous email. Thanks and Regards, Ajay On Mon, Oct 10, 2016 at 2:39 AM, Michael Wojcikwrote: >> From: openssl-users [mailto:openssl-users-boun...@openssl.org] On Behalf >> Of Ajay Garg >> Sent: Sunday, October 09, 2016 14:12 >> >> Also, for all my cases, Nagle's algorithm has been disabled on the >> client as well as the server, so every write (at client/server) >> constitutes a packet-transferred. > > This assumption is incorrect. Nagle is not the only factor which interferes > with a 1-to-1 mapping between application sends and (IP) packets on the wire. > The peer's receive window, the interface and path MTUs, fragmentation, > transient network failures ... many things can either split an application > message into multiple IP packets or even multiple TCP segments, or cause > multiple application messages to be coalesced into a single TCP segment > (which usually is also a single IP packet, now that path MTU determination > usually works properly). > > You should never assume TCP is anything other than a byte-stream service. An > application that makes any assumptions about how its send operations > translate into TCP segments or IP packets is asking for trouble. > > -- > Michael Wojcik > Distinguished Engineer, Micro Focus > > > > -- > openssl-users mailing list > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
> From: openssl-users [mailto:openssl-users-boun...@openssl.org] On Behalf > Of Ajay Garg > Sent: Sunday, October 09, 2016 14:12 > > Also, for all my cases, Nagle's algorithm has been disabled on the > client as well as the server, so every write (at client/server) > constitutes a packet-transferred. This assumption is incorrect. Nagle is not the only factor which interferes with a 1-to-1 mapping between application sends and (IP) packets on the wire. The peer's receive window, the interface and path MTUs, fragmentation, transient network failures ... many things can either split an application message into multiple IP packets or even multiple TCP segments, or cause multiple application messages to be coalesced into a single TCP segment (which usually is also a single IP packet, now that path MTU determination usually works properly). You should never assume TCP is anything other than a byte-stream service. An application that makes any assumptions about how its send operations translate into TCP segments or IP packets is asking for trouble. -- Michael Wojcik Distinguished Engineer, Micro Focus -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
On Sun, Oct 9, 2016 at 10:55 PM, Viktor Dukhovniwrote: > >> On Oct 9, 2016, at 10:47 AM, Ajay Garg wrote: >> >>> However, it might sometimes return SSL_ERROR_WANT_READ, in which >>> case, the SSL layer wants to read, even though the application >>> wants to write. Your job is to do the read on the SSL layer's >>> behalf, and then retry the write. >> >> For this particular sub-case, let's say SSL-layer wants to obtain "n" >> bytes from the socket/wire. >> >> So, in this case, is it ok to do a blocking-read on the socket, unless >> "n" bytes are received (of course, a socket "error" will be handled in >> the blocking-call; it's just that any socket-timeouts will not be >> considered). > > Yes, you can do a blocking read (provided you have already flushed all > pending writes). Thanks a ton Viktor for the reply. (Yes, in the above case I mentioned, all pending writes would have been flushed). Also, I will be grateful if you could let me know if ANY of the sub-flows in ANY of the flows below is wrong, remembering that "bio1" is the SSL-BIO where the app-payload-bytes are written in, and "bio2" is the IN-MEMORY-BIO where the app-payload-encrypted-bytes emerge. app <==> bio1 <==>bio2 <==> socket Also, for all my cases, Nagle's algorithm has been disabled on the client as well as the server, so every write (at client/server) constitutes a packet-transferred. a) Can BIO_write(bio1, buf, n) return a positive, non-zero return-value other than "n"? In other words, is it possible that only partial-bytes are written? b) Let's say BIO_write(bio1, buf, n) was successful in writing "n" bytes to "bio1". So, will ALL the app-payload-encrypted-bytes be available at "bio2" immediately in a synchronous manner (so that they can be immediately sent to the server over the wire) ? Implicit in this workflow is my assumption that SSL too builds up a packet for every BIO_write done over "bio1". c) Will the following sequence happen exactly as follows :: i) App wants to read some bytes, but in a probing manner (bytes may/may-not have been sent by server). ii) Now, currently, "bio1", "bio2", "socket" are in clean-state. Nothing is pending "in the real sense" to be written/read anywhere. iii) When app does BIO_read(bio1) SSL_ERROR_WANT_READ would be returned (after all, "bio1" cannot provide any app-payload-bytes unless it has received any app-payload-encrypted-bytes from server). iv) Doing BIO_get_read_request(bio2) would return 0. v) So, we try reading 1 byte from the socket (in a non-blocking manner, obviously). I successful, we write the 1 byte into "bio2" (and so, "bio1" will get the smell of a new encrypted packet). vi) Thereafter, when app again does BIO_read(bio1), (assuming we do not hit any re-negotiation case in this cycle) this time, BIO_get_read_request(bio2) will return a non-zero value "n". vii) We read the "n" bytes over the wire, and write them to "bio2". viii) Finally, the "m" decrypted-packet-bytes will be available at "bio1", from the encrypted-packet of length "n+1" bytes. Is my story of 8-points in case c) correct? :) I am sorry for bothering you so much, but I can take comfort from the fact that such idiotic questions will help noobs like me integrate openssl faster, with better understanding of the internals, which will obviously lead to slicker code. Thanks again to everyone for the help so far Thanks and Regards, Ajay > > -- > Viktor. > > -- > openssl-users mailing list > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
> On Oct 9, 2016, at 10:47 AM, Ajay Gargwrote: > >> However, it might sometimes return SSL_ERROR_WANT_READ, in which >> case, the SSL layer wants to read, even though the application >> wants to write. Your job is to do the read on the SSL layer's >> behalf, and then retry the write. > > For this particular sub-case, let's say SSL-layer wants to obtain "n" > bytes from the socket/wire. > > So, in this case, is it ok to do a blocking-read on the socket, unless > "n" bytes are received (of course, a socket "error" will be handled in > the blocking-call; it's just that any socket-timeouts will not be > considered). Yes, you can do a blocking read (provided you have already flushed all pending writes). -- Viktor. -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Hi Viktor. On Fri, Oct 7, 2016 at 11:17 PM, Viktor Dukhovniwrote: > On Fri, Oct 07, 2016 at 10:30:06PM +0530, Ajay Garg wrote: > >> Ok, so for sending app-payload-bytes, we do a bio_write() to "bio1", >> and if "bio1" requires reading from bio2/peer, bio_write() will return >> SSL_ERROR_WANT_READ (even for blocking sockets). We then read-in some >> app-payload-encrypted-bytes from device-socket, > > No, it will *usually* return SSL_ERROR_WANT_WRITE, that's when you > write "some" (based on pending data amount from bio2) to the network > that you read from bio2. Those writes might be written via a buffer > you interpose, however it is important to flush that buffer as > much as possible before attempting any network reads (flush fully > if the network reads are potentially blocking). > > However, it might sometimes return SSL_ERROR_WANT_READ, in which > case, the SSL layer wants to read, even though the application > wants to write. Your job is to do the read on the SSL layer's > behalf, and then retry the write. For this particular sub-case, let's say SSL-layer wants to obtain "n" bytes from the socket/wire. So, in this case, is it ok to do a blocking-read on the socket, unless "n" bytes are received (of course, a socket "error" will be handled in the blocking-call; it's just that any socket-timeouts will not be considered). I hope the following is NOT happening internally :: * SSL-layer "advertises" that it wants "n" bytes from socket/wire. * However, in reality, it first wants "x" bytes from socket/wire, then actually wants to send "m" bytes, and then finally wants to receive the remaining "n-x" bytes from socket/wire. I am sure it is not happening, just want to confirm :) > > Where "some" is obtained by queried bio2 for the amount of pending > data. You can loop reading/sending smaller amounts that if the > entire amount is too big to write to the target in one go without > blocking. Otherwise, you need a large enough write buffer downstream. > If you can't fully drain bio2's output in one go, just keep the > socket selected for write and try again later when more space is > available. > >> put them into "bio2" >> (thus internally fulfilling bio1's need for read), and then again try >> bio_write() to "bio1" WITH IDENTICAL APP-PAYLOAD-BYTES. If it again >> returns SSL_ERROR_WANT_READ, we repeat the cycle. > > Well, you may not fulfill that need, if you don't drain all the > pending data, and so the SSL_ERROR_WANT_... may repeat. What you > do with bio2 has no direct relationship on the direction of the > I/O in bio1. Just keep track of whether the crypto wants to read > or write, and whether either bio2 or any buffer you interpose > downstream has pending data. Then move data between the network > and bio2 as appropriate. > >> For reading app-payload-bytes, we do a bio_read() from "bio1", and if >> "bio1" requires writing bytes to bio2/peer, bio_read() will return >> SSL_ERROR_WANT_WRITE (even for blocking sockets). > > No, it will *usually* return SSL_ERROR_WANT_READ, that's when you > read "some" (based on desired read size from bio2) from the network > and write the results to bio2. Those reads might be satisfied from > a buffer you interpose. > > However, it might sometimes return SSL_ERROR_WANT_WRITE, in which > case, the SSL layer wants to write, even though the application wants > to read. Your job is to do the write on the SSL layer's behalf, > and then retry the read. > >> We then pick up the >> app-payload-encrypted-bytes from "bio2", transfer them over the wire >> via device-specific-socket (thus fulfilling bio1's need to send bytes >> to peer), and then again try bio_read() from "bio1" WITH IDENTICAL >> APP-PAYLOAD-BYTES. If it again returns SSL_ERROR_WANT_WRITE, we repeat >> the cycle. > > When retrying app-layer reads, you do not need to provide the same > buffer or read request size on subsequent attempts. > >> Obviously, for the above two sub-plots, the only chance of failure if >> reading/writing bytes fails over the wire. >> But that is not the norm; if it does happen, then everything will be >> restarted from scratch (at least by me). > >> If yes, then it seems everything can be done fully synchronously for >> blocking-sockets, > > No, synchronous operation will not work. The network may not be > ready to receive more data when you're ready to write (network > layer data), or have more data when you're ready to read. Use of > bio-pairs with blocking sockets is highly risky, you'll probably > dead-lock with some regularity. > >> thus eliminating the need of multiple threads, > > You don't need threads, an event loop will do. Indeed an event > loop is generally better, don't know whether the same bio-pair is > safe for use by multiple threads. > > You just need to be able to perform the equivalent of > > select()/poll()/... > > on whatever interface you have for moving data to/from > the network. > > -- > Viktor. > --
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Thanks Viktor. On all our device-types, we are using blocking-sockets, but reads can signal that no data is available (equivalent to SO_RCVTIMEO value set as the socket-option on linux-like systems). It seems you have provided me enough insight to get my hands dirty :) Thanks and Regards, Ajay On Fri, Oct 7, 2016 at 11:17 PM, Viktor Dukhovniwrote: > On Fri, Oct 07, 2016 at 10:30:06PM +0530, Ajay Garg wrote: > >> Ok, so for sending app-payload-bytes, we do a bio_write() to "bio1", >> and if "bio1" requires reading from bio2/peer, bio_write() will return >> SSL_ERROR_WANT_READ (even for blocking sockets). We then read-in some >> app-payload-encrypted-bytes from device-socket, > > No, it will *usually* return SSL_ERROR_WANT_WRITE, that's when you > write "some" (based on pending data amount from bio2) to the network > that you read from bio2. Those writes might be written via a buffer > you interpose, however it is important to flush that buffer as > much as possible before attempting any network reads (flush fully > if the network reads are potentially blocking). > > However, it might sometimes return SSL_ERROR_WANT_READ, in which > case, the SSL layer wants to read, even though the application > wants to write. Your job is to do the read on the SSL layer's > behalf, and then retry the write. > > Where "some" is obtained by queried bio2 for the amount of pending > data. You can loop reading/sending smaller amounts that if the > entire amount is too big to write to the target in one go without > blocking. Otherwise, you need a large enough write buffer downstream. > If you can't fully drain bio2's output in one go, just keep the > socket selected for write and try again later when more space is > available. > >> put them into "bio2" >> (thus internally fulfilling bio1's need for read), and then again try >> bio_write() to "bio1" WITH IDENTICAL APP-PAYLOAD-BYTES. If it again >> returns SSL_ERROR_WANT_READ, we repeat the cycle. > > Well, you may not fulfill that need, if you don't drain all the > pending data, and so the SSL_ERROR_WANT_... may repeat. What you > do with bio2 has no direct relationship on the direction of the > I/O in bio1. Just keep track of whether the crypto wants to read > or write, and whether either bio2 or any buffer you interpose > downstream has pending data. Then move data between the network > and bio2 as appropriate. > >> For reading app-payload-bytes, we do a bio_read() from "bio1", and if >> "bio1" requires writing bytes to bio2/peer, bio_read() will return >> SSL_ERROR_WANT_WRITE (even for blocking sockets). > > No, it will *usually* return SSL_ERROR_WANT_READ, that's when you > read "some" (based on desired read size from bio2) from the network > and write the results to bio2. Those reads might be satisfied from > a buffer you interpose. > > However, it might sometimes return SSL_ERROR_WANT_WRITE, in which > case, the SSL layer wants to write, even though the application wants > to read. Your job is to do the write on the SSL layer's behalf, > and then retry the read. > >> We then pick up the >> app-payload-encrypted-bytes from "bio2", transfer them over the wire >> via device-specific-socket (thus fulfilling bio1's need to send bytes >> to peer), and then again try bio_read() from "bio1" WITH IDENTICAL >> APP-PAYLOAD-BYTES. If it again returns SSL_ERROR_WANT_WRITE, we repeat >> the cycle. > > When retrying app-layer reads, you do not need to provide the same > buffer or read request size on subsequent attempts. > >> Obviously, for the above two sub-plots, the only chance of failure if >> reading/writing bytes fails over the wire. >> But that is not the norm; if it does happen, then everything will be >> restarted from scratch (at least by me). > >> If yes, then it seems everything can be done fully synchronously for >> blocking-sockets, > > No, synchronous operation will not work. The network may not be > ready to receive more data when you're ready to write (network > layer data), or have more data when you're ready to read. Use of > bio-pairs with blocking sockets is highly risky, you'll probably > dead-lock with some regularity. > >> thus eliminating the need of multiple threads, > > You don't need threads, an event loop will do. Indeed an event > loop is generally better, don't know whether the same bio-pair is > safe for use by multiple threads. > > You just need to be able to perform the equivalent of > > select()/poll()/... > > on whatever interface you have for moving data to/from > the network. > > -- > Viktor. > -- > openssl-users mailing list > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
On Fri, Oct 07, 2016 at 10:30:06PM +0530, Ajay Garg wrote: > Ok, so for sending app-payload-bytes, we do a bio_write() to "bio1", > and if "bio1" requires reading from bio2/peer, bio_write() will return > SSL_ERROR_WANT_READ (even for blocking sockets). We then read-in some > app-payload-encrypted-bytes from device-socket, No, it will *usually* return SSL_ERROR_WANT_WRITE, that's when you write "some" (based on pending data amount from bio2) to the network that you read from bio2. Those writes might be written via a buffer you interpose, however it is important to flush that buffer as much as possible before attempting any network reads (flush fully if the network reads are potentially blocking). However, it might sometimes return SSL_ERROR_WANT_READ, in which case, the SSL layer wants to read, even though the application wants to write. Your job is to do the read on the SSL layer's behalf, and then retry the write. Where "some" is obtained by queried bio2 for the amount of pending data. You can loop reading/sending smaller amounts that if the entire amount is too big to write to the target in one go without blocking. Otherwise, you need a large enough write buffer downstream. If you can't fully drain bio2's output in one go, just keep the socket selected for write and try again later when more space is available. > put them into "bio2" > (thus internally fulfilling bio1's need for read), and then again try > bio_write() to "bio1" WITH IDENTICAL APP-PAYLOAD-BYTES. If it again > returns SSL_ERROR_WANT_READ, we repeat the cycle. Well, you may not fulfill that need, if you don't drain all the pending data, and so the SSL_ERROR_WANT_... may repeat. What you do with bio2 has no direct relationship on the direction of the I/O in bio1. Just keep track of whether the crypto wants to read or write, and whether either bio2 or any buffer you interpose downstream has pending data. Then move data between the network and bio2 as appropriate. > For reading app-payload-bytes, we do a bio_read() from "bio1", and if > "bio1" requires writing bytes to bio2/peer, bio_read() will return > SSL_ERROR_WANT_WRITE (even for blocking sockets). No, it will *usually* return SSL_ERROR_WANT_READ, that's when you read "some" (based on desired read size from bio2) from the network and write the results to bio2. Those reads might be satisfied from a buffer you interpose. However, it might sometimes return SSL_ERROR_WANT_WRITE, in which case, the SSL layer wants to write, even though the application wants to read. Your job is to do the write on the SSL layer's behalf, and then retry the read. > We then pick up the > app-payload-encrypted-bytes from "bio2", transfer them over the wire > via device-specific-socket (thus fulfilling bio1's need to send bytes > to peer), and then again try bio_read() from "bio1" WITH IDENTICAL > APP-PAYLOAD-BYTES. If it again returns SSL_ERROR_WANT_WRITE, we repeat > the cycle. When retrying app-layer reads, you do not need to provide the same buffer or read request size on subsequent attempts. > Obviously, for the above two sub-plots, the only chance of failure if > reading/writing bytes fails over the wire. > But that is not the norm; if it does happen, then everything will be > restarted from scratch (at least by me). > If yes, then it seems everything can be done fully synchronously for > blocking-sockets, No, synchronous operation will not work. The network may not be ready to receive more data when you're ready to write (network layer data), or have more data when you're ready to read. Use of bio-pairs with blocking sockets is highly risky, you'll probably dead-lock with some regularity. > thus eliminating the need of multiple threads, You don't need threads, an event loop will do. Indeed an event loop is generally better, don't know whether the same bio-pair is safe for use by multiple threads. You just need to be able to perform the equivalent of select()/poll()/... on whatever interface you have for moving data to/from the network. -- Viktor. -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Thanks for the reply Viktor. On Fri, Oct 7, 2016 at 8:27 PM, Jakob Bohmwrote: > On 07/10/2016 16:35, Ajay Garg wrote: >> >> Hi Viktor. >> >> Thanks for your reply, and I am sorry for being idiotic, OpenSSL does >> seem daunting, but I am learning :) >> >> Also, let's not bother too much about the APIs/methods as such. >> I will be grateful if you could confirm/reject my >> architectural-understanding so far. >> >> Let's say "bio1" is the SSL-BIO, and "bio2" is the In-Memory-BIO, and >> they have been made a pair, with the architecture being :: >> >> App <=> bio1 <=> bio2 <=> device-specific-socket >> > One caveat for both scenarios below: > > RW2a: During step R2 or W2, the SSL/TLS protocol may need to > transmit some data in the opposite direction in order to handle > automatically setting or changing the encryption keys etc. Thus > during W2, some data may be read from bio2 and during R2, some > data may be written to bio2. > > This doesn't happen every time, but it always happens for the > first app-payload-bytes, and it may happen at any later time > subject to changes as the protocol and/or library are improved. Ok, so for sending app-payload-bytes, we do a bio_write() to "bio1", and if "bio1" requires reading from bio2/peer, bio_write() will return SSL_ERROR_WANT_READ (even for blocking sockets). We then read-in some app-payload-encrypted-bytes from device-socket, put them into "bio2" (thus internally fulfilling bio1's need for read), and then again try bio_write() to "bio1" WITH IDENTICAL APP-PAYLOAD-BYTES. If it again returns SSL_ERROR_WANT_READ, we repeat the cycle. For reading app-payload-bytes, we do a bio_read() from "bio1", and if "bio1" requires writing bytes to bio2/peer, bio_read() will return SSL_ERROR_WANT_WRITE (even for blocking sockets). We then pick up the app-payload-encrypted-bytes from "bio2", transfer them over the wire via device-specific-socket (thus fulfilling bio1's need to send bytes to peer), and then again try bio_read() from "bio1" WITH IDENTICAL APP-PAYLOAD-BYTES. If it again returns SSL_ERROR_WANT_WRITE, we repeat the cycle. Obviously, for the above two sub-plots, the only chance of failure if reading/writing bytes fails over the wire. But that is not the norm; if it does happen, then everything will be restarted from scratch (at least by me). Is my understanding correct (especially for the case if blocking-sockets are being used throughout)? If yes, then it seems everything can be done fully synchronously for blocking-sockets, thus eliminating the need of multiple threads, and thus enabling us to integrate OpenSSL seamlessly in our already existing framework across all devices that we have ported our framework to (devices with/without operating-systems, with/without GPRS/Wifi). So, eagerly awaiting your reply :) Thanks a ton for the lightning-quick help so far Thanks and Regards, Ajay > > >> So, for writes, following steps can be made to happen synchronously >> (even with blocking device-specific-sockets) :: >> >> W1. App writes x app-payload-bytes to bio1. >> >> W2. Internally, x app-payload-bytes (at bio1) become y >> app-payload-encrypted-bytes (at bio2). >> >> W3. Thereafter, the y app-payload-encrypted-bytes are transferred >> over the wire via the device-specific-socket. >> >> I think W2 is the key-step architecturally. >> >> >> For reads, following steps can be made to happen synchronously (even >> with blocking device-specific-sockets, carrying read-timeout feature) >> :: >> >>R1. App wants x app-payload-bytes. >> >>R2. If bio1 can produce at least x app-payload-bytes, then we are done. >> >> Else, we read some (let's say n) app-payload-encrypted-bytes >> from device-specific-socket, write them into bio2, and >> again enquire if bio1 can now produce at least x >> app-payload-bytes. >> >> If still not, we keep reading n app-payload-encrypted-bytes >> from device-specific-socket and writing them into bio2, until >> bio1 can produce at least x app-payload-bytes. >> >>R3. Finally, App reads x app-payload-bytes. >> >> Here too, I think R2 is the key-step architecturally. >> >> >> >> Is my above architectural-understanding of the workflow between App >> and Device-Specific-Socket correct? >> >> >> Anyway, thanks for your help so far. >> >> >> Thanks and Regards, >> Ajay >> >> >> >> >> On Fri, Oct 7, 2016 at 3:25 PM, Viktor Dukhovni >> wrote: >>> >>> On Fri, Oct 07, 2016 at 12:28:46PM +0530, Ajay Garg wrote: >>> I realise I am still stuck with the original issue. >>> >>> Failure to read the documentation closely. >>> Also, how do "bio1" and "bio2" communicate in case of non-ideal scenarios (timeouts, errors)? >>> >>> They don't, you move all the data. All reads/writes by OpenSSL will >>> return SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE when the requisite >>> data is not already buffered. At that point you do the
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
On 07/10/2016 16:35, Ajay Garg wrote: Hi Viktor. Thanks for your reply, and I am sorry for being idiotic, OpenSSL does seem daunting, but I am learning :) Also, let's not bother too much about the APIs/methods as such. I will be grateful if you could confirm/reject my architectural-understanding so far. Let's say "bio1" is the SSL-BIO, and "bio2" is the In-Memory-BIO, and they have been made a pair, with the architecture being :: App <=> bio1 <=> bio2 <=> device-specific-socket One caveat for both scenarios below: RW2a: During step R2 or W2, the SSL/TLS protocol may need to transmit some data in the opposite direction in order to handle automatically setting or changing the encryption keys etc. Thus during W2, some data may be read from bio2 and during R2, some data may be written to bio2. This doesn't happen every time, but it always happens for the first app-payload-bytes, and it may happen at any later time subject to changes as the protocol and/or library are improved. So, for writes, following steps can be made to happen synchronously (even with blocking device-specific-sockets) :: W1. App writes x app-payload-bytes to bio1. W2. Internally, x app-payload-bytes (at bio1) become y app-payload-encrypted-bytes (at bio2). W3. Thereafter, the y app-payload-encrypted-bytes are transferred over the wire via the device-specific-socket. I think W2 is the key-step architecturally. For reads, following steps can be made to happen synchronously (even with blocking device-specific-sockets, carrying read-timeout feature) :: R1. App wants x app-payload-bytes. R2. If bio1 can produce at least x app-payload-bytes, then we are done. Else, we read some (let's say n) app-payload-encrypted-bytes from device-specific-socket, write them into bio2, and again enquire if bio1 can now produce at least x app-payload-bytes. If still not, we keep reading n app-payload-encrypted-bytes from device-specific-socket and writing them into bio2, until bio1 can produce at least x app-payload-bytes. R3. Finally, App reads x app-payload-bytes. Here too, I think R2 is the key-step architecturally. Is my above architectural-understanding of the workflow between App and Device-Specific-Socket correct? Anyway, thanks for your help so far. Thanks and Regards, Ajay On Fri, Oct 7, 2016 at 3:25 PM, Viktor Dukhovniwrote: On Fri, Oct 07, 2016 at 12:28:46PM +0530, Ajay Garg wrote: I realise I am still stuck with the original issue. Failure to read the documentation closely. Also, how do "bio1" and "bio2" communicate in case of non-ideal scenarios (timeouts, errors)? They don't, you move all the data. All reads/writes by OpenSSL will return SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE when the requisite data is not already buffered. At that point you do the requsite I/O and copy data into and out of the network bio. First, do all pending writes: BIO_ctrl_pending(network_bio) BIO_read(network_bio, ...) ... write the opaque ciphertext to the underlying socket-like ... thing when it is writable, take to not block or drop ... the ciphertext on the floor if you do. then if SSL_ERROR_WANT_READ, find out how much OpenSSL wants to read, and read that much data from the underlying socket-like thing and copy its (opaque ciphertext) into the network bio: BIO_ctrl_get_read_request(network_bio) BIO_write(network_bio, ...) A double-buffer (separate read/write) between the socket and SSL may make the logic simpler, but the write side must be flushed whenever to the SSL network BIO becomes empty, to avoid deadlock. And of course avoid blocking on reads when it is OpenSSL's turn to write. In general you have an event loop, a non-blocking socket thingy, and select/poll/... read/write or both depending on SSL_ERROR_WANT_READ/WRITE and the state of any intermediate buffers you're managing. A careful read of the manpage will expose all these facilities. Enjoy Jakob -- Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10 This public discussion message is non-binding and may contain errors. WiseMo - Remote Service Management for PCs, Phones and Embedded -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Hi Viktor. Thanks for your reply, and I am sorry for being idiotic, OpenSSL does seem daunting, but I am learning :) Also, let's not bother too much about the APIs/methods as such. I will be grateful if you could confirm/reject my architectural-understanding so far. Let's say "bio1" is the SSL-BIO, and "bio2" is the In-Memory-BIO, and they have been made a pair, with the architecture being :: App <=> bio1 <=> bio2 <=> device-specific-socket So, for writes, following steps can be made to happen synchronously (even with blocking device-specific-sockets) :: W1. App writes x app-payload-bytes to bio1. W2. Internally, x app-payload-bytes (at bio1) become y app-payload-encrypted-bytes (at bio2). W3. Thereafter, the y app-payload-encrypted-bytes are transferred over the wire via the device-specific-socket. I think W2 is the key-step architecturally. For reads, following steps can be made to happen synchronously (even with blocking device-specific-sockets, carrying read-timeout feature) :: R1. App wants x app-payload-bytes. R2. If bio1 can produce at least x app-payload-bytes, then we are done. Else, we read some (let's say n) app-payload-encrypted-bytes from device-specific-socket, write them into bio2, and again enquire if bio1 can now produce at least x app-payload-bytes. If still not, we keep reading n app-payload-encrypted-bytes from device-specific-socket and writing them into bio2, until bio1 can produce at least x app-payload-bytes. R3. Finally, App reads x app-payload-bytes. Here too, I think R2 is the key-step architecturally. Is my above architectural-understanding of the workflow between App and Device-Specific-Socket correct? Anyway, thanks for your help so far. Thanks and Regards, Ajay On Fri, Oct 7, 2016 at 3:25 PM, Viktor Dukhovniwrote: > On Fri, Oct 07, 2016 at 12:28:46PM +0530, Ajay Garg wrote: > >> I realise I am still stuck with the original issue. > > Failure to read the documentation closely. > >> Also, how do "bio1" and "bio2" communicate in case of non-ideal >> scenarios (timeouts, errors)? > > They don't, you move all the data. All reads/writes by OpenSSL will > return SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE when the requisite > data is not already buffered. At that point you do the requsite > I/O and copy data into and out of the network bio. > > First, do all pending writes: > > BIO_ctrl_pending(network_bio) > BIO_read(network_bio, ...) > > ... write the opaque ciphertext to the underlying socket-like > ... thing when it is writable, take to not block or drop > ... the ciphertext on the floor if you do. > > then if SSL_ERROR_WANT_READ, find out how much OpenSSL wants to > read, and read that much data from the underlying socket-like thing > and copy its (opaque ciphertext) into the network bio: > > BIO_ctrl_get_read_request(network_bio) > BIO_write(network_bio, ...) > > A double-buffer (separate read/write) between the socket and SSL > may make the logic simpler, but the write side must be flushed > whenever to the SSL network BIO becomes empty, to avoid deadlock. > And of course avoid blocking on reads when it is OpenSSL's turn to > write. In general you have an event loop, a non-blocking socket > thingy, and select/poll/... read/write or both depending on > SSL_ERROR_WANT_READ/WRITE and the state of any intermediate buffers > you're managing. > > A careful read of the manpage will expose all these facilities. > > -- > Viktor. > -- > openssl-users mailing list > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
On Fri, Oct 07, 2016 at 12:28:46PM +0530, Ajay Garg wrote: > I realise I am still stuck with the original issue. Failure to read the documentation closely. > Also, how do "bio1" and "bio2" communicate in case of non-ideal > scenarios (timeouts, errors)? They don't, you move all the data. All reads/writes by OpenSSL will return SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE when the requisite data is not already buffered. At that point you do the requsite I/O and copy data into and out of the network bio. First, do all pending writes: BIO_ctrl_pending(network_bio) BIO_read(network_bio, ...) ... write the opaque ciphertext to the underlying socket-like ... thing when it is writable, take to not block or drop ... the ciphertext on the floor if you do. then if SSL_ERROR_WANT_READ, find out how much OpenSSL wants to read, and read that much data from the underlying socket-like thing and copy its (opaque ciphertext) into the network bio: BIO_ctrl_get_read_request(network_bio) BIO_write(network_bio, ...) A double-buffer (separate read/write) between the socket and SSL may make the logic simpler, but the write side must be flushed whenever to the SSL network BIO becomes empty, to avoid deadlock. And of course avoid blocking on reads when it is OpenSSL's turn to write. In general you have an event loop, a non-blocking socket thingy, and select/poll/... read/write or both depending on SSL_ERROR_WANT_READ/WRITE and the state of any intermediate buffers you're managing. A careful read of the manpage will expose all these facilities. -- Viktor. -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
Victor, I realise I am still stuck with the original issue. Taking "bio1" as the SSL-facing-bio, and "bio2" as the network-facing-bio, how do we write-into/read-from "bio2"? Are there callbacks available that will allow :: * Writing to network via "bio2" (after "bio1" has internally-transferred the bytes to "bio2") ? * Reading from network via "bio2" (after which "bio1" can internally-pick-up the bytes from "bio2") ? Also, how do "bio1" and "bio2" communicate in case of non-ideal scenarios (timeouts, errors)? On Fri, Oct 7, 2016 at 10:09 AM, Ajay Gargwrote: > On Fri, Oct 7, 2016 at 9:19 AM, Viktor Dukhovni > wrote: >> On Fri, Oct 07, 2016 at 08:51:24AM +0530, Ajay Garg wrote: >> >>> However, I am a bit unsure about certain implementations. >>> In particular (let's talk only about the client-side), I wonder how do >>> the following methods work internally :: >>> >>> >>> * SSL_connect (implicitly involving underlying-socket-reads and >>> underlying-socket-writes) >> >> Correct. >> >>> * SSL_write (involving underlying-socket-writes) >> >> This can also involve socket reads, e.g. when the peer requests >> renegotiation. Hence, on non-blocking sockets this can fail with >> SSL_ERROR_WANT_READ. The application should then retry the write >> (generally with the identitical data) when the socket becomes >> *readable*. >> >>> * SSL_read (involving underlying-socket-reads) >> >> This can also involve socket writes, e.g. when the peer requests >> renegotiation. Hence, on non-blocking sockets this can fail with >> SSL_ERROR_WANT_WRITE. The application should then retry the read >> when the socket becomes *writable*. >> >>> We have a framework which we have ported to a variety of devices, >>> involving GPRS-connectivity, and devices without operating-systems. >>> I know that there is "no one universal socket-write" and "no one >>> universal socket-read" implementations. >> >> No idea what "root-level" means. Perhaps you mean something >> analogous to a system-call? If so OpenSSL can either be handed >> the socket to use, or plugged into some other way of moving data >> via the BIO pair interface. >> >> https://www.openssl.org/docs/manmaster/crypto/BIO_s_bio.html > > > A let me have a look.. I think this will fit in :) > >> >> -- >> Viktor. >> --. >> openssl-users mailing list >> To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users > > > > -- > Regards, > Ajay -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"
On Fri, Oct 7, 2016 at 9:19 AM, Viktor Dukhovniwrote: > On Fri, Oct 07, 2016 at 08:51:24AM +0530, Ajay Garg wrote: > >> However, I am a bit unsure about certain implementations. >> In particular (let's talk only about the client-side), I wonder how do >> the following methods work internally :: >> >> >> * SSL_connect (implicitly involving underlying-socket-reads and >> underlying-socket-writes) > > Correct. > >> * SSL_write (involving underlying-socket-writes) > > This can also involve socket reads, e.g. when the peer requests > renegotiation. Hence, on non-blocking sockets this can fail with > SSL_ERROR_WANT_READ. The application should then retry the write > (generally with the identitical data) when the socket becomes > *readable*. > >> * SSL_read (involving underlying-socket-reads) > > This can also involve socket writes, e.g. when the peer requests > renegotiation. Hence, on non-blocking sockets this can fail with > SSL_ERROR_WANT_WRITE. The application should then retry the read > when the socket becomes *writable*. > >> We have a framework which we have ported to a variety of devices, >> involving GPRS-connectivity, and devices without operating-systems. >> I know that there is "no one universal socket-write" and "no one >> universal socket-read" implementations. > > No idea what "root-level" means. Perhaps you mean something > analogous to a system-call? If so OpenSSL can either be handed > the socket to use, or plugged into some other way of moving data > via the BIO pair interface. > > https://www.openssl.org/docs/manmaster/crypto/BIO_s_bio.html A let me have a look.. I think this will fit in :) > > -- > Viktor. > --. > openssl-users mailing list > To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users -- Regards, Ajay -- openssl-users mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users