Discussion:
Schannel and Session Renegotiation
(too old to reply)
Mark M.
2003-08-28 18:23:40 UTC
Permalink
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)

A question regarding SSL session key renegotiation in SChannel.

(FYI - Vishal has previously pointed out that in fact CLIENT-side initiated
Session Renegotiation is NOT supported by SChannel on W2K(before SP5) or WXP
(before SP2). The first time thats been mentioned anywhere by MS AFAIK)

Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)

Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?

Detail:
1. A server requests a renegotiation by sending a HELLO_REQUEST, that the
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.

2. The client can then kick off a new handshake loop at its leisure (the
server MAY enforce the renegotiation, or it may not). The client could in
fact ignore the request...lets say it'd like to comply.....

3. The client makes repeated calls to InitializeSecurityContext() during the
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the renegotiation
proper.

4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....

BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read()
application layer records (not "handshake" records) "from-the-wire" -
sent by the server before IT received the
initial CLIENT_HELLO.

If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?

There is no reason for the server NOT to continue sending encrypted data
having requested a renegotiation, as it is allowed for the client to ignore
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop sending
further encrypted data.

One _could_ have a look at the records as they come in (during the handshake
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]

But isn't the API supposed to take care of that kind of stuff.....?

Any further insight would be much appreciated. .......(a bit long I know -
but then again what do you expect with such an unwieldy API.....)

Thanks a lot folks

Regards......................Mark.
Vishal Mishra [MS]
2003-08-28 20:22:24 UTC
Permalink
Server (non-anonymous) can ask for renegotiation in 3 cases:

1- Upfront the server can ask a client to authenticate and send the client
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel does
this)
Server initiated renegotiation requires:
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;

2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the hello_request. I
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a hello_request it
then kicks off a new handshake by sending a client_hello.

RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
When this message will be sent:
The hello request message may be sent by the server at any time.
Meaning of this message:
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.

After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.

Structure of this message:
struct { } HelloRequest;

Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.

HOW Schannel generates hello_request:
//
// Build encrypted hello_request message.
//

dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;

InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;

InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;

OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;

OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;

Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);

3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is the case
where the server may not close the connection as its only wanting to refresh
keys and the client doesn't want to. The implementation is the same way as
above for case2.

Also, some comments inline.....

Hope this helps. If I have missed something then please ask again as this
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side initiated
Session Renegotiation is NOT supported by SChannel on W2K(before SP5) or WXP
(before SP2). The first time thats been mentioned anywhere by MS AFAIK)
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST, that the
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure (the
server MAY enforce the renegotiation, or it may not). The client could in
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client does
not send a client_hello as the resource requested requires authentication.
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext() during the
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the renegotiation
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read() application layer records (not "handshake" records)
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I beleive)
send app data after requesting a renegotiation. It waits for the client to
send a client_hello and then depending on application, it can either close
the connection with a fatal error or continue servicing client requests. TCP
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake dance
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted data
having requested a renegotiation, as it is allowed for the client to ignore
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop sending
further encrypted data.
One _could_ have a look at the records as they come in (during the handshake
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I know -
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Falcon
2003-09-02 17:41:08 UTC
Permalink
Hi Vishal,

I also have an issue with Session Renegotiation that maybe you can
shed some light on. I am implementing an Schannel Client to
communicate with BIGIP (OpenSSL) host.

I can invoke Session Key renegotiation from the client end using
USE_SESSION_KEY in the InitializeSecurityContext, with the current
credentials and context information. But I also want to renegotiate a
new session completely as well, I have attempted this in two ways,
both of which are refused by the BIGIP host:

Method 1 - Create a new security context via ISC and send the new
ClientHello to the host. This is refused by the host, apparently the
host does not recognise it as a valid request as the context has now
changed.

Method 2 - Using the current context and credential information, call
ISC with empty input buffers, again send the output to the host. The
host recognises this as a resumption request of the previous session.

After discussing this with the BIGIP expert, the host is expecting a
resumption request with no Session ID field.

I see no way of being able to produce what the host expects, is there
another way to perform Session Renegotiation from the client end.

Thanks in advance,
Falcon
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the client
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel does
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the hello_request. I
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a hello_request it
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is the case
where the server may not close the connection as its only wanting to refresh
keys and the client doesn't want to. The implementation is the same way as
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as this
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before SP5) or
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS AFAIK)
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST, that the
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure (the
server MAY enforce the renegotiation, or it may not). The client could in
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client does
not send a client_hello as the resource requested requires authentication.
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext() during
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the renegotiation
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read() application layer records (not "handshake" records)
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I beleive)
send app data after requesting a renegotiation. It waits for the client to
send a client_hello and then depending on application, it can either close
the connection with a fatal error or continue servicing client requests. TCP
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake dance
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted data
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I know -
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Vishal Mishra [MS]
2003-09-02 19:03:51 UTC
Permalink
I replied to Mark a few days back that Schannel does not support client
initiated renegotiation on W2K and XP as yet though fixes have been made for
W2K SP5 and XP SP2.

it is supported on Windows Server 2003 and NT. I have pasted the code below
to perform it on those platforms.

//
// Initiate a client_hello message and generate a token.
//

OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].cbBuffer = 0;

OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
OutBuffer.ulVersion = SECBUFFER_VERSION;

scRet = g_pSSPI->InitializeSecurityContextA(
phCreds,
phContext,
pszServerName,
dwSSPIFlags,
0,
SECURITY_NATIVE_DREP,
NULL,
0,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
&tsExpiry);

if(scRet != SEC_I_CONTINUE_NEEDED) {
printf(__FUNCTION__": **** Error 0x%x returned by
InitializeSecurityContext\n", scRet);
return scRet;
}

// Send response to server if there is one.
if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
{
cbData = send(Socket,
OutBuffers[0].pvBuffer,
OutBuffers[0].cbBuffer,
0);

// Free output buffer.
g_pSSPI->FreeContextBuffer(OutBuffers[0].pvBuffer);
OutBuffers[0].pvBuffer = NULL;
}
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Falcon
Hi Vishal,
I also have an issue with Session Renegotiation that maybe you can
shed some light on. I am implementing an Schannel Client to
communicate with BIGIP (OpenSSL) host.
I can invoke Session Key renegotiation from the client end using
USE_SESSION_KEY in the InitializeSecurityContext, with the current
credentials and context information. But I also want to renegotiate a
new session completely as well, I have attempted this in two ways,
Method 1 - Create a new security context via ISC and send the new
ClientHello to the host. This is refused by the host, apparently the
host does not recognise it as a valid request as the context has now
changed.
Method 2 - Using the current context and credential information, call
ISC with empty input buffers, again send the output to the host. The
host recognises this as a resumption request of the previous session.
After discussing this with the BIGIP expert, the host is expecting a
resumption request with no Session ID field.
I see no way of being able to produce what the host expects, is there
another way to perform Session Renegotiation from the client end.
Thanks in advance,
Falcon
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the client
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel does
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the
hello_request. I
Post by Falcon
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a
hello_request it
Post by Falcon
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is the case
where the server may not close the connection as its only wanting to refresh
keys and the client doesn't want to. The implementation is the same way as
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as this
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before SP5) or
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS AFAIK)
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST, that the
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure (the
server MAY enforce the renegotiation, or it may not). The client could in
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client does
not send a client_hello as the resource requested requires
authentication.
Post by Falcon
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext() during
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read() application layer records (not "handshake" records)
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I beleive)
send app data after requesting a renegotiation. It waits for the client to
send a client_hello and then depending on application, it can either close
the connection with a fatal error or continue servicing client requests. TCP
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake dance
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted data
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I know -
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Mark M.
2003-09-03 10:35:58 UTC
Permalink
See some comments inline...
some inline comments.
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Falcon
Hi Vishal,
I also have an issue with Session Renegotiation that maybe you can
shed some light on. I am implementing an Schannel Client to
communicate with BIGIP (OpenSSL) host.
I can invoke Session Key renegotiation from the client end using
USE_SESSION_KEY in the InitializeSecurityContext, with the current
credentials and context information. But I also want to renegotiate a
new session completely as well, I have attempted this in two ways,
[vishal] I don't know what the USE_SESSION_KEY does in this case.
When you call ISC in this way, it simply generates a new client_hello with
the existing "session id" (if the cache item has not expired) which when
you
send across results in a "reconnection" or a "renegotiation" depending on
how the server behaves. In Schannel, this leads to a renegotiation but I
don't know how other server implementations behave.
[Mark] One possible reason why Falcon is attempting to use USE_SESSION_KEY
in the Context Attributes of the ISC call is that the docs say .. (and I
quote)....

USE_SESSION_KEY : A new session key must be negotiated.

What can I say other than "Improve the docs!"..
Post by Falcon
Method 1 - Create a new security context via ISC and send the new
ClientHello to the host. This is refused by the host, apparently the
host does not recognise it as a valid request as the context has now
changed.
[vishal] This is obvious..:) The server has the old keys and will error
out
as it cannot decrypt the data you sent across.
[Mark] It is probably worth explaining ( for everyones benefit!) that SSL
employs both unencrypted AND encrypted handshake messages. Of course before
shared session keys have been negotiated and until the CHANGE_CIPHER_SPEC
message is sent - each side sends UNencrypted handshake messages. This is
what ISC returns if called for the first time with a NEW security context -
an UNencrypted CLIENT_HELLO, expecting to start a NEW "session" (which
possibly may be "resumed"..!)
As Vishal points out, whether or not there is an existing or NULL session ID
depends on the state of the local session cache ( no easy access to the
session ID's with SChannel it seems). The server barfs coz it expects an
ENCRYPTED handshake message (encrypted with the old session keys of
course) - not coz its got the "wrong" keys!

This method *could* work however, but you would have to explicitly
terminiate the SSL session first by sending a CLOSE_NOTIFY to the server.
(This is described reasonably well in the WebClient sample from the SDK) The
problem then is that you need to guarantee that the BIGIP OpenSSL server
will keep the underlying TCP transport open (not USUALLY the case with
OpenSSL server implementations - they will usually pull down the underlying
socket on receipt of a CLOSE_NOTIFY - but thats a question for F5 I
guess....!)
Post by Falcon
Method 2 - Using the current context and credential information, call
ISC with empty input buffers, again send the output to the host. The
host recognises this as a resumption request of the previous session.
[vishal] How is this bad in any way? A "reconnect" generates new keys as
well. It uses the old session (if within the session cache expiry time) if
possible for performance reasons. Such a re-connect is way faster and
provides you new keys as well, which is the objective right?
[Mark] If using the current context & credential info & called with empty
buffers, ISC generates an encrypted CLIENT_HELLO - which is a valid
renegotiate request.I don't see how OpenSSL could possibly interpret this as
a "new" session. Lets be careful about the difference between resumption &
renegotiation:

RESUMPTION: Client sends UNencrypted CLIENT_HELLO. If session ID field is
zero, its a brand-new session. If session ID field is non-zero, server can
optionally choose to re-use cached session credentials
by responding with the same session ID in its SERVER_HELLO. If it
can't/won't use session caching,
then it'll respond with a new session ID. In either case, the Session Keys
are NEW.

RENEGOTIATION: Server can ask for a renegotiation be sending an encrypted
HELLO_REQUEST.
Client can ignore this, send an alert, or comply by sending an encrypted
CLIENT_HELLO (encrypted with the
existing session keys.) Handshake proceeds as above with encrypted handshake
messages , with new session
keys coming into play with immediately after sending CHANGE_CIPHER_SPEC.

Renegotiation in the manner you describe simply may not be
supported/implemeted correctly on the OpenSSL server.....??
Post by Falcon
After discussing this with the BIGIP expert, the host is expecting a
resumption request with no Session ID field.
I see no way of being able to produce what the host expects, is there
another way to perform Session Renegotiation from the client end.
[vishal] There might be a hack for it but do you really want to use it?
[Mark] This doesn't make sense. The server should be perfectly happy to
accept ANY allowed value in the session ID field. It up to it to decide if
it has cached that session (id) & wants to "resume", or if it wants to
ignore the clients sesson renegotiation request & begin a brand new session.
OpenSSL handles this fairly transparently. However, if it explicity refuses
to talk to ANY client requesting a session resumption (which I very much
doubt)
then as Vishal says you could simply force the session id to zero once you
get the CLIENT_HELLO back from ISC. I agree with Vishal in that it should
not be necessary - the server is broken if it is.....
Post by Falcon
Thanks in advance,
Falcon
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the
client
Post by Falcon
Post by Vishal Mishra [MS]
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel
does
Post by Falcon
Post by Vishal Mishra [MS]
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the
hello_request. I
Post by Falcon
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a
hello_request it
Post by Falcon
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is
the
case
Post by Falcon
Post by Vishal Mishra [MS]
where the server may not close the connection as its only wanting to
refresh
Post by Falcon
Post by Vishal Mishra [MS]
keys and the client doesn't want to. The implementation is the same
way
as
Post by Falcon
Post by Vishal Mishra [MS]
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as
this
Post by Falcon
Post by Vishal Mishra [MS]
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no
rights.
Post by Falcon
Post by Vishal Mishra [MS]
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before
SP5)
or
Post by Falcon
Post by Vishal Mishra [MS]
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS
AFAIK)
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST,
that
the
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure
(the
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
server MAY enforce the renegotiation, or it may not). The client
could
in
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client
does
Post by Falcon
Post by Vishal Mishra [MS]
not send a client_hello as the resource requested requires
authentication.
Post by Falcon
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext()
during
Post by Falcon
Post by Vishal Mishra [MS]
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Falcon
Post by Vishal Mishra [MS]
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Falcon
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
to
Post by Falcon
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Falcon
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client
requests.
TCP
Post by Falcon
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start
sending
Post by Falcon
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Falcon
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted
data
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I
know -
Post by Falcon
Post by Vishal Mishra [MS]
Post by Mark M.
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Vishal Mishra [MS]
2003-09-02 18:54:31 UTC
Permalink
I looked deep into this and I am of the opinion now that after the server
sends out a hello_request there is no way it SHOULD be sending any app data.
The implementation does not support it.
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Thanks Vishal for your detailed answer, which does help clear up some
issues, but unfortunately is not the answer I've been looking for.....
I am interested in a situation where a "generic" SSL server wants to
re-negotiate the sesion keys...(definitely recomended for long-lived
sessions) ... but is happy to continue if the client decides its OK not
to -
the client dictates policy in this regard.
So I guess as far as the server is concerned its scenario 3 that you
outlined below...
The problem is that in this case the server should continue happily
sending
app data UNTIL it gets a CLIENT_HELLO... (that seems reasonable behaviour
to
me, [e.g. in a proxy?] in the case where renegotiation is not mandatory -
it
is certainly allowed by the spec).......
--- SNIP ---
Post by Vishal Mishra [MS]
Post by Mark M.
BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read() application layer records (not "handshake" records)
"from-the-wire" - sent by the server before IT received the initial
CLIENT_HELLO.
Post by Vishal Mishra [MS]
[vishal mishra] The server does not (should not?, app dependent I beleive)
send app data after requesting a renegotiation. It waits for the client to
send a client_hello and then depending on application, it can either close
the connection with a fatal error or continue servicing client requests.
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the existing
session keys.
--- END SNIP ---
From this answer it seems that SChannel will barf if it gets app data
while
in the ASC/ISC handshake "dance". [ ISC = InitializeSecurityContext, ASC =
AcceptSecurityContext]
Q: IS THIS THE CASE??
I fear it is - and this is probably (?) related to why Client-side
initiated
renegotiation is not supported.
The core problem is that SChannel provides no way to distinguish app data
from handshake data. Sure - DecryptMessage() "knows" about HELLO_REQUEST
but
it seems that ISC cannot handle Encrypted Application data, and thats what
is needed.......let me elborate..
It appears that SChannel only allows ISC calls with a NULL Security
Context
(new session) or with an existing Security Context after receiving a
HELLO_REQUEST. After the first ISC call passing in empty buffers to
generate
the CLIENT_HELLO, no application data is allowed until the handshake is
complete & ISC returns SEC_E_OK. This explains why Client-side initiated
renegotiations are not supported. In this case the server has no way of
knowing it should stop sending app data, hence ISC is potentially in
trouble....
For what its worth, a possible solution could be for ISC to return
decrypted
app data with a specific rv (SEC_E_APP_DATA?) if it is received from the
server & passed into ISC during the initial stages of the handshake loop
(before the app gets the SERVER_HELLO.)
Note that ISC must decrypt the encrypted handshake messages during a
renegotiation anyway...
it should be easy to recognise, decrypt & return app data.
Of course once the SERVER_HELLO IS received, app data is not allowed & an
error should be returned if it is.
What do you think MS....?
As it stands, the server _cannot_ send app data after sending the
HELLO_REQUEST - it must continue to deal with incoming data on the old
session keys, but either die or forget about the renegotiaion request of
it
does not get a CLIENT_HELLO within some app-dependent time (or received
number of data records...)
I must say the spec (see below) is loose on this point.
--- SNIP ---
Post by Vishal Mishra [MS]
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
--- END SNIP ---
So can you confirm that ISC will not accept Encrypted App data before the
ISC handshake loop returns SEC_E_OK ?
Thanks again......
Regards...............Mark
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the client
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel
does
Post by Vishal Mishra [MS]
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the
hello_request.
I
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a
hello_request
it
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is the
case
Post by Vishal Mishra [MS]
where the server may not close the connection as its only wanting to
refresh
Post by Vishal Mishra [MS]
keys and the client doesn't want to. The implementation is the same way as
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as this
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before SP5)
or
Post by Vishal Mishra [MS]
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS AFAIK)
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST, that
the
Post by Vishal Mishra [MS]
Post by Mark M.
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure (the
server MAY enforce the renegotiation, or it may not). The client could
in
Post by Vishal Mishra [MS]
Post by Mark M.
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client does
not send a client_hello as the resource requested requires
authentication.
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext()
during
Post by Vishal Mishra [MS]
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is entirely
possible to read() application layer records (not "handshake" records)
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I beleive)
send app data after requesting a renegotiation. It waits for the client to
send a client_hello and then depending on application, it can either close
the connection with a fatal error or continue servicing client requests.
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted data
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I
know -
Post by Vishal Mishra [MS]
Post by Mark M.
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Mark M.
2003-09-03 11:32:31 UTC
Permalink
Vishal -
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the server
sends out a hello_request there is no way it SHOULD be sending any app data.
The implementation does not support it.
Which of the following do you mean?

1. The server CANNOT send any app data after sending the HELLO_REQUEST as
the implementation(SChannel) does not support receipt of app data at any
stage once ISC has been called for the first time in a handshake loop. In
this case the server must be designed to "behave properly" with an Schannel
client. This is what I think you mean (& what I observe!)

2. The server SHOULD not send any app data as SSL does not support this.
This I do not believe to be true. An SSL implementation COULD and SHOULD
support the receipt of app data at certain stages of the renegotiation
handshake (both client AND server). Referring to you earlier comments below
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start sending
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake dance
but is in the loop where it accepts and decrypts data with the existing
session keys.
The problem is that in the generic case the server does not KNOW apriori
whether or not the client
will support renegotiation! The spec says its optional for the client. So
the server continues sending
app data as you say. Then the client decides to renegotiate.This scheme
currently breaks with an SChannel client for reason 1 above!
So it seems I must force the server to wait until after the handshake is
complete before sending any more app
data. This present more problems: How do I find out if it completed ? (A
problem [not yours!] for some OPENSSL-based servers...!) How long do I give
the client to start & complete the renegotiation? I cannot assume/expect
it'll start immediatlely....etc.etc...) So you see - by not supporting
receipt of encrypted app data after handshake requests the option of the
client ignoring the request is effectively removed. I hope this will be
addressed in future versions of SChannel.

This is not an easy issue & I appreciate you taking the time to think about
it. I think the SSL spec is sufficiently
loose on session renegotiation to allow for SSL implementors to be sloppy
with it. However, given the ever-increasing use of SSL beyond it original
design goals (in particular VPN - type apps, which could have very
long-lived sessions) its time the implementors took note. OpenSSL & SChannel
are probably the 2 most popular SSL implementations out there. OpenSSL has
(recently!) addressed session renegotiation. Perhaps its time MS did the
same with SChannel?

Thanks again Vishal.

Regards...............

Mark.
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the server
sends out a hello_request there is no way it SHOULD be sending any app data.
The implementation does not support it.
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Thanks Vishal for your detailed answer, which does help clear up some
issues, but unfortunately is not the answer I've been looking for.....
I am interested in a situation where a "generic" SSL server wants to
re-negotiate the sesion keys...(definitely recomended for long-lived
sessions) ... but is happy to continue if the client decides its OK not
to -
the client dictates policy in this regard.
So I guess as far as the server is concerned its scenario 3 that you
outlined below...
The problem is that in this case the server should continue happily
sending
app data UNTIL it gets a CLIENT_HELLO... (that seems reasonable behaviour
to
me, [e.g. in a proxy?] in the case where renegotiation is not mandatory -
it
is certainly allowed by the spec).......
--- SNIP ---
Post by Vishal Mishra [MS]
Post by Mark M.
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
Post by Mark M.
"from-the-wire" - sent by the server before IT received the initial
CLIENT_HELLO.
Post by Vishal Mishra [MS]
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client requests.
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the existing
session keys.
--- END SNIP ---
From this answer it seems that SChannel will barf if it gets app data
while
in the ASC/ISC handshake "dance". [ ISC = InitializeSecurityContext, ASC =
AcceptSecurityContext]
Q: IS THIS THE CASE??
I fear it is - and this is probably (?) related to why Client-side
initiated
renegotiation is not supported.
The core problem is that SChannel provides no way to distinguish app data
from handshake data. Sure - DecryptMessage() "knows" about HELLO_REQUEST
but
it seems that ISC cannot handle Encrypted Application data, and thats what
is needed.......let me elborate..
It appears that SChannel only allows ISC calls with a NULL Security
Context
(new session) or with an existing Security Context after receiving a
HELLO_REQUEST. After the first ISC call passing in empty buffers to
generate
the CLIENT_HELLO, no application data is allowed until the handshake is
complete & ISC returns SEC_E_OK. This explains why Client-side initiated
renegotiations are not supported. In this case the server has no way of
knowing it should stop sending app data, hence ISC is potentially in
trouble....
For what its worth, a possible solution could be for ISC to return
decrypted
app data with a specific rv (SEC_E_APP_DATA?) if it is received from the
server & passed into ISC during the initial stages of the handshake loop
(before the app gets the SERVER_HELLO.)
Note that ISC must decrypt the encrypted handshake messages during a
renegotiation anyway...
it should be easy to recognise, decrypt & return app data.
Of course once the SERVER_HELLO IS received, app data is not allowed & an
error should be returned if it is.
What do you think MS....?
As it stands, the server _cannot_ send app data after sending the
HELLO_REQUEST - it must continue to deal with incoming data on the old
session keys, but either die or forget about the renegotiaion request of
it
does not get a CLIENT_HELLO within some app-dependent time (or received
number of data records...)
I must say the spec (see below) is loose on this point.
--- SNIP ---
Post by Vishal Mishra [MS]
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
--- END SNIP ---
So can you confirm that ISC will not accept Encrypted App data before the
ISC handshake loop returns SEC_E_OK ?
Thanks again......
Regards...............Mark
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the
client
Post by Vishal Mishra [MS]
certificate. This is during the initial handshake and the server sends a
"certificate_request" message (pass the flag bewlo to ASC and Schannel
does
Post by Vishal Mishra [MS]
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access protected
resource, then the server can initiate a renegotiation to ask for client
authentication. This is the case where the server sends the
hello_request.
I
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel generates
this message via the code below. When the client reveices a
hello_request
it
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any time.
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the request
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes which
are maintained throughout the handshake and used in the finished
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server may
close the connection if it does not receive a client_hello, this is the
case
Post by Vishal Mishra [MS]
where the server may not close the connection as its only wanting to
refresh
Post by Vishal Mishra [MS]
keys and the client doesn't want to. The implementation is the same
way
Post by Vishal Mishra [MS]
as
Post by Vishal Mishra [MS]
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as
this
Post by Vishal Mishra [MS]
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no
rights.
Post by Vishal Mishra [MS]
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before SP5)
or
Post by Vishal Mishra [MS]
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS
AFAIK)
Post by Vishal Mishra [MS]
Post by Mark M.
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the server
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST, that
the
Post by Vishal Mishra [MS]
Post by Mark M.
clients DecrpytMessage() recognises by returning SEC_I_RENEGOTIATE.
2. The client can then kick off a new handshake loop at its leisure
(the
Post by Vishal Mishra [MS]
Post by Mark M.
server MAY enforce the renegotiation, or it may not). The client could
in
Post by Vishal Mishra [MS]
Post by Mark M.
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client
does
Post by Vishal Mishra [MS]
not send a client_hello as the resource requested requires
authentication.
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and the
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext()
during
Post by Vishal Mishra [MS]
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client requests.
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does not
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data. The
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the existing
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled by
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data that
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted
data
Post by Vishal Mishra [MS]
Post by Mark M.
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16 for
Handshake messages]
Then pass any App records to DecryptMessage, until we get a Handshake
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I
know -
Post by Vishal Mishra [MS]
Post by Mark M.
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Vishal Mishra [MS]
2003-09-03 22:18:42 UTC
Permalink
Thanx for the in-depth analysis!

As you rightly observed, Schannel does not support the server sending app
data after sending a hello_request. It must receive a client_hello and
renegotiate a new handshake or else it will error out.
The RFC provides different ways for the server to react after sending a
hello_request, Schannel simply decided to support the below.
From Section 7.4.1.1 Hello Request:
"If the server sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert."

We are discussing the option of providing support for the client blowing off
the hello_request but I can't say if it be done.

I understand the requirements of long-lived sessions and thats where client
initiated renegotiation support came into the picture and was supported. I
don't see how the above support will effect that?

As for session renegotiation; Windows Server 2003, W2K SP5 and XP SP2
provide renegotiation support from both server and client side....:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Vishal -
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the server
sends out a hello_request there is no way it SHOULD be sending any app
data.
Post by Vishal Mishra [MS]
The implementation does not support it.
Which of the following do you mean?
1. The server CANNOT send any app data after sending the HELLO_REQUEST as
the implementation(SChannel) does not support receipt of app data at any
stage once ISC has been called for the first time in a handshake loop. In
this case the server must be designed to "behave properly" with an Schannel
client. This is what I think you mean (& what I observe!)
2. The server SHOULD not send any app data as SSL does not support this.
This I do not believe to be true. An SSL implementation COULD and SHOULD
support the receipt of app data at certain stages of the renegotiation
handshake (both client AND server). Referring to you earlier comments below
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
The problem is that in the generic case the server does not KNOW apriori
whether or not the client
will support renegotiation! The spec says its optional for the client. So
the server continues sending
app data as you say. Then the client decides to renegotiate.This scheme
currently breaks with an SChannel client for reason 1 above!
So it seems I must force the server to wait until after the handshake is
complete before sending any more app
data. This present more problems: How do I find out if it completed ? (A
problem [not yours!] for some OPENSSL-based servers...!) How long do I give
the client to start & complete the renegotiation? I cannot assume/expect
it'll start immediatlely....etc.etc...) So you see - by not supporting
receipt of encrypted app data after handshake requests the option of the
client ignoring the request is effectively removed. I hope this will be
addressed in future versions of SChannel.
This is not an easy issue & I appreciate you taking the time to think about
it. I think the SSL spec is sufficiently
loose on session renegotiation to allow for SSL implementors to be sloppy
with it. However, given the ever-increasing use of SSL beyond it original
design goals (in particular VPN - type apps, which could have very
long-lived sessions) its time the implementors took note. OpenSSL & SChannel
are probably the 2 most popular SSL implementations out there. OpenSSL has
(recently!) addressed session renegotiation. Perhaps its time MS did the
same with SChannel?
Thanks again Vishal.
Regards...............
Mark.
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the server
sends out a hello_request there is no way it SHOULD be sending any app
data.
Post by Vishal Mishra [MS]
The implementation does not support it.
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Vishal Mishra [MS]
Thanks Vishal for your detailed answer, which does help clear up some
issues, but unfortunately is not the answer I've been looking for.....
I am interested in a situation where a "generic" SSL server wants to
re-negotiate the sesion keys...(definitely recomended for long-lived
sessions) ... but is happy to continue if the client decides its OK not
to -
the client dictates policy in this regard.
So I guess as far as the server is concerned its scenario 3 that you
outlined below...
The problem is that in this case the server should continue happily
sending
app data UNTIL it gets a CLIENT_HELLO... (that seems reasonable
behaviour
Post by Vishal Mishra [MS]
to
me, [e.g. in a proxy?] in the case where renegotiation is not
mandatory -
Post by Vishal Mishra [MS]
it
is certainly allowed by the spec).......
--- SNIP ---
Post by Vishal Mishra [MS]
Post by Mark M.
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
Post by Mark M.
"from-the-wire" - sent by the server before IT received the initial
CLIENT_HELLO.
Post by Vishal Mishra [MS]
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client
requests.
Post by Vishal Mishra [MS]
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
--- END SNIP ---
From this answer it seems that SChannel will barf if it gets app data
while
in the ASC/ISC handshake "dance". [ ISC = InitializeSecurityContext,
ASC
Post by Mark M.
=
Post by Vishal Mishra [MS]
AcceptSecurityContext]
Q: IS THIS THE CASE??
I fear it is - and this is probably (?) related to why Client-side
initiated
renegotiation is not supported.
The core problem is that SChannel provides no way to distinguish app
data
Post by Vishal Mishra [MS]
from handshake data. Sure - DecryptMessage() "knows" about
HELLO_REQUEST
Post by Mark M.
Post by Vishal Mishra [MS]
but
it seems that ISC cannot handle Encrypted Application data, and thats
what
Post by Vishal Mishra [MS]
is needed.......let me elborate..
It appears that SChannel only allows ISC calls with a NULL Security
Context
(new session) or with an existing Security Context after receiving a
HELLO_REQUEST. After the first ISC call passing in empty buffers to
generate
the CLIENT_HELLO, no application data is allowed until the handshake is
complete & ISC returns SEC_E_OK. This explains why Client-side initiated
renegotiations are not supported. In this case the server has no way of
knowing it should stop sending app data, hence ISC is potentially in
trouble....
For what its worth, a possible solution could be for ISC to return
decrypted
app data with a specific rv (SEC_E_APP_DATA?) if it is received from the
server & passed into ISC during the initial stages of the handshake
loop
Post by Vishal Mishra [MS]
(before the app gets the SERVER_HELLO.)
Note that ISC must decrypt the encrypted handshake messages during a
renegotiation anyway...
it should be easy to recognise, decrypt & return app data.
Of course once the SERVER_HELLO IS received, app data is not allowed &
an
Post by Vishal Mishra [MS]
error should be returned if it is.
What do you think MS....?
As it stands, the server _cannot_ send app data after sending the
HELLO_REQUEST - it must continue to deal with incoming data on the old
session keys, but either die or forget about the renegotiaion request of
it
does not get a CLIENT_HELLO within some app-dependent time (or received
number of data records...)
I must say the spec (see below) is loose on this point.
--- SNIP ---
Post by Vishal Mishra [MS]
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any
time.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the
request
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
until the subsequent handshake negotiation is complete.
--- END SNIP ---
So can you confirm that ISC will not accept Encrypted App data before
the
Post by Vishal Mishra [MS]
ISC handshake loop returns SEC_E_OK ?
Thanks again......
Regards...............Mark
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the
client
Post by Vishal Mishra [MS]
certificate. This is during the initial handshake and the server
sends
Post by Mark M.
a
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
"certificate_request" message (pass the flag bewlo to ASC and Schannel
does
Post by Vishal Mishra [MS]
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access
protected
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
resource, then the server can initiate a renegotiation to ask for
client
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
authentication. This is the case where the server sends the
hello_request.
I
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel
generates
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
this message via the code below. When the client reveices a
hello_request
it
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any
time.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes, respond
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application data,
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the server
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the
request
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes
which
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
are maintained throughout the handshake and used in the
finished
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server
may
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
close the connection if it does not receive a client_hello, this is
the
Post by Vishal Mishra [MS]
case
Post by Vishal Mishra [MS]
where the server may not close the connection as its only wanting to
refresh
Post by Vishal Mishra [MS]
keys and the client doesn't want to. The implementation is the same
way
Post by Vishal Mishra [MS]
as
Post by Vishal Mishra [MS]
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as
this
Post by Vishal Mishra [MS]
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no
rights.
Post by Vishal Mishra [MS]
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before
SP5)
Post by Vishal Mishra [MS]
or
Post by Vishal Mishra [MS]
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS
AFAIK)
Post by Vishal Mishra [MS]
Post by Mark M.
Anyway - here goes for SERVER-side initiated Renegotation (the usual
scenario...)
Question: How are Encrypted Application Layer Records from the
server
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST,
that
Post by Vishal Mishra [MS]
the
Post by Vishal Mishra [MS]
Post by Mark M.
clients DecrpytMessage() recognises by returning
SEC_I_RENEGOTIATE.
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
2. The client can then kick off a new handshake loop at its leisure
(the
Post by Vishal Mishra [MS]
Post by Mark M.
server MAY enforce the renegotiation, or it may not). The client
could
Post by Vishal Mishra [MS]
in
Post by Vishal Mishra [MS]
Post by Mark M.
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client
does
Post by Vishal Mishra [MS]
not send a client_hello as the resource requested requires
authentication.
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and
the
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to InitializeSecurityContext()
during
Post by Vishal Mishra [MS]
the
Post by Mark M.
handshake loop, the first one passing in empty buffers & building a
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it into
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client
requests.
Post by Vishal Mishra [MS]
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC handshake
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled
by
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
InitializeSecurityContext().
This works fine if the records are indeed all handshake records, but
what is InitializeSecurityContext()'s behaviour if passed in data
that
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending encrypted
data
Post by Vishal Mishra [MS]
Post by Mark M.
having requested a renegotiation, as it is allowed for the client to
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should stop
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16
for
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
Handshake messages]
Then pass any App records to DecryptMessage, until we get a
Handshake
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of stuff.....?
Any further insight would be much appreciated. .......(a bit long I
know -
Post by Vishal Mishra [MS]
Post by Mark M.
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Mark M.
2003-09-04 09:59:29 UTC
Permalink
Comments inline.....
Post by Vishal Mishra [MS]
Thanx for the in-depth analysis!
As you rightly observed, Schannel does not support the server sending app
data after sending a hello_request. It must receive a client_hello and
renegotiate a new handshake or else it will error out.
The RFC provides different ways for the server to react after sending a
hello_request, Schannel simply decided to support the below.
"If the server sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert."
[Mark] OK - I'm glad we've got that clear. While the RFC clearly provides
for several options as regards what each end could do wrt renegotiation, I
believe it should not be SChannels decision to support ONE method only!
THAT is an application-dependent decision! MS appear to be saying: Our
(SChannel) server will never send app data after sending a HELLO_REQUEST, so
our SChannel clients will not support receipt of app data once in the
ISC/ASC loop. And thats my problem - SChannel clients occasionally talking
to non-SChannel clients.
Post by Vishal Mishra [MS]
We are discussing the option of providing support for the client blowing off
the hello_request but I can't say if it be done.
[Mark] I have had no problems with SChannel under W2k SP2 simply IGNORING a
renegotiation request when talking to an OpenSSL server that chooses to
follow different allowed behaviour - NOT requiring a
CLIENT_HELLO immediately after sending the HELLO_REQUEST. Of course if the
server expects a CLIENT_HELLO immediately - then we are broken. But this is
a server policy/implementation issue - NOT a problem with OpenSSL - unlike
the SChannel app!

However, I imagined
Post by Vishal Mishra [MS]
I understand the requirements of long-lived sessions and thats where client
initiated renegotiation support came into the picture and was supported. I
don't see how the above support will effect that?
[Mark] The Client-initiated renegotiation support would certainly help
matters, and the above support would NOT affect that. It is however affected
by the main problem I've been trying to get a handle on during this
discussion. I.E. - it will require the client (ISC in particular) to be
happy to accept app data up until receipt of the SERVER_HELLO reply.
The problem is NOT the SChannel server-side implementation in this case, but
the client.
After starting an unasked-for renegotiation, by entering the ISC loop, it
MUST be able to handle receipt of
encrypted app data! Until that is supported renegotiation will not reliably
work
Post by Vishal Mishra [MS]
As for session renegotiation; Windows Server 2003, W2K SP5 and XP SP2
provide renegotiation support from both server and client side....:)
[Mark] Thanks Vishal, but I still don't think it'll work from the
client-side with a generic server where there is no guarantee that app data
will arrive to ISC BEFORE the SERVER_HELLO...!! This is a serious flaw in
the SChannel implementation IMHO.

Thanks again.

Regards..............Mark
Post by Vishal Mishra [MS]
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no rights.
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Vishal -
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the
server
Post by Mark M.
Post by Vishal Mishra [MS]
sends out a hello_request there is no way it SHOULD be sending any app
data.
Post by Vishal Mishra [MS]
The implementation does not support it.
Which of the following do you mean?
1. The server CANNOT send any app data after sending the HELLO_REQUEST as
the implementation(SChannel) does not support receipt of app data at any
stage once ISC has been called for the first time in a handshake loop. In
this case the server must be designed to "behave properly" with an
Schannel
Post by Mark M.
client. This is what I think you mean (& what I observe!)
2. The server SHOULD not send any app data as SSL does not support this.
This I do not believe to be true. An SSL implementation COULD and SHOULD
support the receipt of app data at certain stages of the renegotiation
handshake (both client AND server). Referring to you earlier comments
below
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC
handshake
Post by Mark M.
dance
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
The problem is that in the generic case the server does not KNOW apriori
whether or not the client
will support renegotiation! The spec says its optional for the client. So
the server continues sending
app data as you say. Then the client decides to renegotiate.This scheme
currently breaks with an SChannel client for reason 1 above!
So it seems I must force the server to wait until after the handshake is
complete before sending any more app
data. This present more problems: How do I find out if it completed ? (A
problem [not yours!] for some OPENSSL-based servers...!) How long do I
give
Post by Mark M.
the client to start & complete the renegotiation? I cannot assume/expect
it'll start immediatlely....etc.etc...) So you see - by not supporting
receipt of encrypted app data after handshake requests the option of the
client ignoring the request is effectively removed. I hope this will be
addressed in future versions of SChannel.
This is not an easy issue & I appreciate you taking the time to think
about
Post by Mark M.
it. I think the SSL spec is sufficiently
loose on session renegotiation to allow for SSL implementors to be sloppy
with it. However, given the ever-increasing use of SSL beyond it original
design goals (in particular VPN - type apps, which could have very
long-lived sessions) its time the implementors took note. OpenSSL &
SChannel
Post by Mark M.
are probably the 2 most popular SSL implementations out there. OpenSSL has
(recently!) addressed session renegotiation. Perhaps its time MS did the
same with SChannel?
Thanks again Vishal.
Regards...............
Mark.
Post by Vishal Mishra [MS]
I looked deep into this and I am of the opinion now that after the
server
Post by Mark M.
Post by Vishal Mishra [MS]
sends out a hello_request there is no way it SHOULD be sending any app
data.
Post by Vishal Mishra [MS]
The implementation does not support it.
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no
rights.
Post by Mark M.
Post by Vishal Mishra [MS]
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Post by Vishal Mishra [MS]
Thanks Vishal for your detailed answer, which does help clear up some
issues, but unfortunately is not the answer I've been looking for.....
I am interested in a situation where a "generic" SSL server wants to
re-negotiate the sesion keys...(definitely recomended for long-lived
sessions) ... but is happy to continue if the client decides its OK
not
Post by Mark M.
Post by Vishal Mishra [MS]
to -
the client dictates policy in this regard.
So I guess as far as the server is concerned its scenario 3 that you
outlined below...
The problem is that in this case the server should continue happily
sending
app data UNTIL it gets a CLIENT_HELLO... (that seems reasonable
behaviour
Post by Vishal Mishra [MS]
to
me, [e.g. in a proxy?] in the case where renegotiation is not
mandatory -
Post by Vishal Mishra [MS]
it
is certainly allowed by the spec).......
--- SNIP ---
Post by Vishal Mishra [MS]
Post by Mark M.
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
Post by Mark M.
"from-the-wire" - sent by the server before IT received the
initial
Post by Mark M.
Post by Vishal Mishra [MS]
CLIENT_HELLO.
Post by Vishal Mishra [MS]
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client
requests.
Post by Vishal Mishra [MS]
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC
handshake
Post by Mark M.
Post by Vishal Mishra [MS]
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
--- END SNIP ---
From this answer it seems that SChannel will barf if it gets app data
while
in the ASC/ISC handshake "dance". [ ISC = InitializeSecurityContext,
ASC
Post by Mark M.
=
Post by Vishal Mishra [MS]
AcceptSecurityContext]
Q: IS THIS THE CASE??
I fear it is - and this is probably (?) related to why Client-side
initiated
renegotiation is not supported.
The core problem is that SChannel provides no way to distinguish app
data
Post by Vishal Mishra [MS]
from handshake data. Sure - DecryptMessage() "knows" about
HELLO_REQUEST
Post by Mark M.
Post by Vishal Mishra [MS]
but
it seems that ISC cannot handle Encrypted Application data, and thats
what
Post by Vishal Mishra [MS]
is needed.......let me elborate..
It appears that SChannel only allows ISC calls with a NULL Security
Context
(new session) or with an existing Security Context after receiving a
HELLO_REQUEST. After the first ISC call passing in empty buffers to
generate
the CLIENT_HELLO, no application data is allowed until the handshake
is
Post by Mark M.
Post by Vishal Mishra [MS]
complete & ISC returns SEC_E_OK. This explains why Client-side
initiated
Post by Mark M.
Post by Vishal Mishra [MS]
renegotiations are not supported. In this case the server has no way
of
Post by Mark M.
Post by Vishal Mishra [MS]
knowing it should stop sending app data, hence ISC is potentially in
trouble....
For what its worth, a possible solution could be for ISC to return
decrypted
app data with a specific rv (SEC_E_APP_DATA?) if it is received from
the
Post by Mark M.
Post by Vishal Mishra [MS]
server & passed into ISC during the initial stages of the handshake
loop
Post by Vishal Mishra [MS]
(before the app gets the SERVER_HELLO.)
Note that ISC must decrypt the encrypted handshake messages during a
renegotiation anyway...
it should be easy to recognise, decrypt & return app data.
Of course once the SERVER_HELLO IS received, app data is not allowed &
an
Post by Vishal Mishra [MS]
error should be returned if it is.
What do you think MS....?
As it stands, the server _cannot_ send app data after sending the
HELLO_REQUEST - it must continue to deal with incoming data on the old
session keys, but either die or forget about the renegotiaion
request
Post by Vishal Mishra [MS]
of
Post by Mark M.
Post by Vishal Mishra [MS]
it
does not get a CLIENT_HELLO within some app-dependent time (or
received
Post by Mark M.
Post by Vishal Mishra [MS]
number of data records...)
I must say the spec (see below) is loose on this point.
--- SNIP ---
Post by Vishal Mishra [MS]
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any
time.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes,
respond
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application
data,
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
it is expected that the negotiation will begin before no more
than a few records are received from the client. If the
server
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the
request
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
until the subsequent handshake negotiation is complete.
--- END SNIP ---
So can you confirm that ISC will not accept Encrypted App data before
the
Post by Vishal Mishra [MS]
ISC handshake loop returns SEC_E_OK ?
Thanks again......
Regards...............Mark
Post by Vishal Mishra [MS]
1- Upfront the server can ask a client to authenticate and send the
client
Post by Vishal Mishra [MS]
certificate. This is during the initial handshake and the server
sends
Post by Mark M.
a
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
"certificate_request" message (pass the flag bewlo to ASC and
Schannel
Post by Mark M.
Post by Vishal Mishra [MS]
does
Post by Vishal Mishra [MS]
this)
dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
2- After the initial handshake, the client requests an access
protected
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
resource, then the server can initiate a renegotiation to ask for
client
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
authentication. This is the case where the server sends the
hello_request.
I
Post by Vishal Mishra [MS]
have pasted the relevant portion from the RFC and how Schannel
generates
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
this message via the code below. When the client reveices a
hello_request
it
Post by Vishal Mishra [MS]
then kicks off a new handshake by sending a client_hello.
RFC TLS1.0: http://www.ietf.org/rfc/rfc2246.txt
7.4.1.1. Hello request
The hello request message may be sent by the server at any
time.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Hello request is a simple notification that the client should
begin the negotiation process anew by sending a client hello
message when convenient. This message will be ignored by the
client if the client is currently negotiating a session. This
message may be ignored by the client if it does not wish to
renegotiate a session, or the client may, if it wishes,
respond
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
with a no_renegotiation alert. Since handshake messages are
intended to have transmission precedence over application
data,
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
it is expected that the negotiation will begin before no mo
re
Post by Vishal Mishra [MS]
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
than a few records are received from the client. If the
server
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
sends a hello request but does not receive a client hello in
response, it may close the connection with a fatal alert.
After sending a hello request, servers should not repeat the
request
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
until the subsequent handshake negotiation is complete.
struct { } HelloRequest;
Note: This message should never be included in the message hashes
which
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
are maintained throughout the handshake and used in the
finished
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
messages and the certificate verify message.
//
// Build encrypted hello_request message.
//
dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
ASC_REQ_REPLAY_DETECT |
ASC_REQ_CONFIDENTIALITY |
ASC_REQ_EXTENDED_ERROR |
ASC_REQ_ALLOCATE_MEMORY |
ASC_REQ_STREAM;
InBuffers[0].BufferType = SECBUFFER_EMPTY;
InBuffers[0].pvBuffer = NULL;
InBuffers[0].cbBuffer = 0;
InBuffer.ulVersion = SECBUFFER_VERSION;
InBuffer.cBuffers = 1;
InBuffer.pBuffers = InBuffers;
OutBuffers[0].BufferType = SECBUFFER_TOKEN;
OutBuffers[0].pvBuffer = NULL;
OutBuffers[0].cbBuffer = 0;
OutBuffer.ulVersion = SECBUFFER_VERSION;
OutBuffer.cBuffers = 1;
OutBuffer.pBuffers = OutBuffers;
Status = g_SecurityFunc.AcceptSecurityContext
(
hCred,
hContext,
&InBuffer,
dwSSPIFlags,
SECURITY_NATIVE_DREP,
NULL,
&OutBuffer,
&dwSSPIOutFlags,
NULL);
3- To refresh keys.
This is application dependent. The RFC states above that the server
may
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
close the connection if it does not receive a client_hello, this is
the
Post by Vishal Mishra [MS]
case
Post by Vishal Mishra [MS]
where the server may not close the connection as its only wanting to
refresh
Post by Vishal Mishra [MS]
keys and the client doesn't want to. The implementation is the same
way
Post by Vishal Mishra [MS]
as
Post by Vishal Mishra [MS]
above for case2.
Also, some comments inline.....
Hope this helps. If I have missed something then please ask again as
this
Post by Vishal Mishra [MS]
mail was a bit comprehensive to catch all queries..:)
--
Vishal Mishra [MSFT]
This posting is provided "AS IS" with no warranties and confers no
rights.
Post by Vishal Mishra [MS]
Use of any included samples is subject to the terms specified at
http://www.microsoft.com/info/copyright.htm"
-------------------------------------------------------------------------
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
Hi Folks - (in particular Vishal Mishra & John Banes from MS...)
A question regarding SSL session key renegotiation in SChannel.
(FYI - Vishal has previously pointed out that in fact CLIENT-side
initiated
Post by Mark M.
Session Renegotiation is NOT supported by SChannel on W2K(before
SP5)
Post by Vishal Mishra [MS]
or
Post by Vishal Mishra [MS]
WXP
Post by Mark M.
(before SP2). The first time thats been mentioned anywhere by MS
AFAIK)
Post by Vishal Mishra [MS]
Post by Mark M.
Anyway - here goes for SERVER-side initiated Renegotation (the
usual
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
scenario...)
Question: How are Encrypted Application Layer Records from the
server
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
handled by an Schannel client
during a Session renegotiation?
1. A server requests a renegotiation by sending a HELLO_REQUEST,
that
Post by Vishal Mishra [MS]
the
Post by Vishal Mishra [MS]
Post by Mark M.
clients DecrpytMessage() recognises by returning
SEC_I_RENEGOTIATE.
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
2. The client can then kick off a new handshake loop at its
leisure
Post by Mark M.
Post by Vishal Mishra [MS]
(the
Post by Vishal Mishra [MS]
Post by Mark M.
server MAY enforce the renegotiation, or it may not). The client
could
Post by Vishal Mishra [MS]
in
Post by Vishal Mishra [MS]
Post by Mark M.
fact ignore the request...lets say it'd like to comply.....
[vishal mishra] The server SHOULD close the connection if the client
does
Post by Vishal Mishra [MS]
not send a client_hello as the resource requested requires
authentication.
Post by Vishal Mishra [MS]
The case where it may continue is when it wants to refresh keys and
the
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client disagrees. This is application dependent.
Post by Mark M.
3. The client makes repeated calls to
InitializeSecurityContext()
Post by Vishal Mishra [MS]
Post by Mark M.
Post by Vishal Mishra [MS]
during
Post by Vishal Mishra [MS]
the
Post by Mark M.
handshake loop, the first one passing in empty buffers &
building
Post by Vishal Mishra [MS]
a
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
CLIENT_HELLO, which it sends back to the server begin the
renegotiation
Post by Vishal Mishra [MS]
Post by Mark M.
proper.
4. The client read() 's data returned by the server & passes it
into
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
InitializeSecurityContext() until complete....
BUT: PROBLEM: When a client is in a "handshake loop" in it is
entirely
Post by Vishal Mishra [MS]
Post by Mark M.
possible to read() application layer records (not "handshake"
records)
Post by Vishal Mishra [MS]
"from-the-wire" -
Post by Mark M.
sent by the server before IT received the
initial CLIENT_HELLO.
[vishal mishra] The server does not (should not?, app dependent I
beleive)
Post by Vishal Mishra [MS]
send app data after requesting a renegotiation. It waits for the
client
Post by Vishal Mishra [MS]
to
Post by Vishal Mishra [MS]
send a client_hello and then depending on application, it can either
close
Post by Vishal Mishra [MS]
the connection with a fatal error or continue servicing client
requests.
Post by Vishal Mishra [MS]
TCP
Post by Vishal Mishra [MS]
guarantees that client gets all app data before the hello_request.
This seems like an application dependent issue. If your server does
not
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
require client_hello after requesting for it then it should start
sending
Post by Vishal Mishra [MS]
the data out and the client should handle that like other app data.
The
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
client did not send a client_hello so its not in the ISC/ASC
handshake
Post by Mark M.
Post by Vishal Mishra [MS]
dance
Post by Vishal Mishra [MS]
but is in the loop where it accepts and decrypts data with the
existing
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
session keys.
Post by Mark M.
If the SDK samples are followed, these records will all be handled
by
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
InitializeSecurityContext().
This works fine if the records are indeed all handshake records,
but
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
what is InitializeSecurityContext()'s behaviour if passed in data
that
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
contains an application layer record encrypted
with the "old" session keys?
There is no reason for the server NOT to continue sending
encrypted
Post by Mark M.
Post by Vishal Mishra [MS]
data
Post by Vishal Mishra [MS]
Post by Mark M.
having requested a renegotiation, as it is allowed for the
client
Post by Vishal Mishra [MS]
to
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
ignore
Post by Mark M.
the renegotiate request!
Of course once the server receives the CLIENT_HELLO - it should
stop
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
sending
Post by Mark M.
further encrypted data.
One _could_ have a look at the records as they come in (during the
handshake
Post by Mark M.
loop) & explicitly check for handshake type messages
[first byte in the record - 0x17 for application layer data, 0x16
for
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
Handshake messages]
Then pass any App records to DecryptMessage, until we get a
Handshake
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
message, at which point we continue
with our InitializeSecurityContext loop as normal.
[ Even then - whats to stop the Handshake message being another
HELLO_REQUEST, which is properly handled by DecryptMessage ???? ]
But isn't the API supposed to take care of that kind of
stuff.....?
Post by Mark M.
Post by Vishal Mishra [MS]
Post by Vishal Mishra [MS]
Post by Mark M.
Any further insight would be much appreciated. .......(a bit
long
Post by Vishal Mishra [MS]
I
Post by Mark M.
Post by Vishal Mishra [MS]
know -
Post by Vishal Mishra [MS]
Post by Mark M.
but then again what do you expect with such an unwieldy API.....)
Thanks a lot folks
Regards......................Mark.
Loading...