Re: [openssl-users] Root-Level queries while using SSL-connections wrapping "sockets"

2016-10-10 Thread Ajay Garg
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"

2016-10-09 Thread Ajay Garg
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"

2016-10-09 Thread Michael Wojcik
> 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"

2016-10-09 Thread Ajay Garg
On Sun, Oct 9, 2016 at 10:55 PM, Viktor Dukhovni
 wrote:
>
>> 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"

2016-10-09 Thread Viktor Dukhovni

> 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).

-- 
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"

2016-10-09 Thread Ajay Garg
Hi Viktor.

On Fri, Oct 7, 2016 at 11:17 PM, Viktor Dukhovni
 wrote:
> 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"

2016-10-07 Thread Ajay Garg
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 Dukhovni
 wrote:
> 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"

2016-10-07 Thread Viktor Dukhovni
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"

2016-10-07 Thread Ajay Garg
Thanks for the reply Viktor.

On Fri, Oct 7, 2016 at 8:27 PM, Jakob Bohm  wrote:
> 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"

2016-10-07 Thread Jakob Bohm

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 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 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"

2016-10-07 Thread Ajay Garg
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 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 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"

2016-10-07 Thread Viktor Dukhovni
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"

2016-10-07 Thread Ajay Garg
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 Garg  wrote:
> 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"

2016-10-06 Thread Ajay Garg
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
-- 
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users