How to handle SEC_I_MESSAGE_FRAGMENT when performing a DTLS handshake via the SChannel SSPI?

Haddon CD 21 Reputation points
2021-05-10T00:37:10.597+00:00

When performing a DTLS handshake using the SChannel SSPI in Windows 10 - for which there is no documentation - how should the application handle a SEC_I_MESSAGE_FRAGMENT result from AcceptSecurityContext (ASC) or InitializeSecurityContext (ISC)?

I understand that I am meant to send the recieved fragment to the other party and call ASC/ISC again to obtain the next fragment, but when I call ASC again, this time with an empty input SECBUFFER_TOKEN, I receive nothing in the output token buffer, and it returns SEC_I_MESSAGE_FRAGMENT - suggesting it is expecting input data.

Presumably I am not successfully indicating to ASC that I want it to give me the next fragment, so how do I do this?

I have created a standalone example that reproduces my issue in this GitHub gist:
https://gist.github.com/haddoncd/381c5e9542e977ca238ff16229bd9a0e/c881132ced94995402b617f38a5c8b6f8669b637

I have also included in the gist example output from the program which shows in detail the inputs that lead to the issue:
https://gist.github.com/haddoncd/381c5e9542e977ca238ff16229bd9a0e/c881132ced94995402b617f38a5c8b6f8669b637#file-example_output-txt

Windows development Windows API - Win32
{count} votes

Accepted answer
  1. Pu Xu 81 Reputation points Microsoft Employee
    2021-09-07T21:29:45.197+00:00

    According to my test, the only WRONG thing you did is forget to RESET context.handle once initialized during handshaking.

    c
    isc_status = InitializeSecurityContextW(
        &creds,
        context.initialized ? &context.handle : nullptr,
        nullptr,
        context_reqs,
        0,
        SECURITY_NATIVE_DREP,
        isc_input_buffers,
        0,
        &context.handle, // HERE
        &out_buffer_desc,
        &context.attrs,
        &context.expiry
    );
    
    asc_status = AcceptSecurityContext(
        &creds,
        context.initialized ? &context.handle : nullptr,
        &in_buffer_desc,
        context_reqs,
        SECURITY_NATIVE_DREP,
        &context.handle, // HERE
        &out_buffer_desc,
        &context.attrs,
        &context.expiry
    );
    

    BTW, you don't need to call DeleteSecurityContext on the old CtxtHandle because it's been invalid after the call.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.