通过 SChannel SSPI 执行 DTLS 握手时如何处理 SEC_I_MESSAGE_FRAGMENT?

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

在 Windows10 中使用 SChannel SSPI 执行 DTLS 握手时 - 没有相关文档 - 应用程序应如何处理来自 AcceptSecurityContext (ASC) 或 InitializeSecurityContext (ISC) 的 SEC_I_MESSAGE_FRAGMENT 结果)?

我明白我的意思是将收到的片段发送给对方并再次调用ASC/ISC以获得下一个片段,但是当我再次调用ASC时,这次输入为空SECBUFFER_TOKEN,我在输出令牌缓冲区中没有收到任何东西,它 returns SEC_I_MESSAGE_FRAGMENT - 表明它正在等待输入数据。

大概我没有成功地向 ASC 表明我希望它给我下一个片段,那么我该怎么做呢?

我创建了一个独立的示例,它在这个 GitHub 要点中重现了我的问题: https://gist.github.com/haddoncd/381c5e9542e977ca238ff16229bd9a0e/c881132ced94995402b617f38a5c8b6f8669b637

我还在程序的要点示例输出中包含了该程序的要点示例输出,其中详细显示了导致问题的输入: https://gist.github.com/haddoncd/381c5e9542e977ca238ff16229bd9a0e/c881132ced94995402b617f38a5c8b6f8669b637#file-example_output-txt

根据我的测试,你做的唯一错误就是在握手过程中初始化后忘记重置 context.handle

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

顺便说一句,您不需要在旧的 CtxtHandle 上调用 DeleteSecurityContext,因为它在调用后已失效。

关于您的实施的问题:我注意到您没有指定您正在使用的协议。

如 SCHANNEL_CRED docs 中所述,您可以通过设置 schannel_cred.grbitEnabledProtocols = SP_PROT_DTLS1_2_CLIENT (或 1.1,服务器等),然后调用 AcquireCredentialsHandle。您是如何验证使用 DTLS 的连接的?文档说“如果此成员为零,则 Schannel 选择协议”。