2

I want to use Microsoft's Security Support Provider Interface (SSPI) in a Windows Domain environment (with Kerberos) to send encrypted and signed messages between two entities (in C++).

Based on the documentation within the MSDN, there are the two functions MakeSignature() and EncryptMessage() [1] but the documentation as well as the example code [2] do not explicitly anwser the question of how to send data encrypted and signed (according to encrypt-than-mac).

Can anyone confirm that I have to use manually invoke EncryptMessage() and MakeSignature() in sequence to get to the desired result? Or do I miss something there and EncryptMessage() has a way to directly create a signature of the encrypted data?

[1] MSDN documentation of EncryptMessage() and MakeSignature() https://msdn.microsoft.com/en-us/library/windows/desktop/aa378736(v=vs.85).aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/aa375378(v=vs.85).aspx

[2] MSDN Example Code https://msdn.microsoft.com/en-us/library/windows/desktop/aa380531(v=vs.85).aspx

---- Reply to Remus Rusanu's answer 2017-03-09 ---------------------------

Thanks @Remus Rusanu for your answer, I didn't take the GSSAPI interoperability document into account yet.

Here it is stated that "GSS_Wrap and GSS_Unwrap are used for both integrity and privacy with the use of privacy controlled by the value of the "conf_flag" argument." and that "The SSPI equivalent to GSS_Wrap is EncryptMessage (Kerberos) for both integrity and privacy".

You said that "EncryptMessage [...] will do the signing too, if the negotiated context requires it.". This means for me, that the at least the following fContextReq flags need to be set for InitializeSecurityContext():

  • ISC_REQ_CONFIDENTIALITY
  • ISC_REQ_INTEGRITY

Can you (or somebody else) can confirm this?

---- Update 2017-03-16 ----------------------------------------------------------------

After further research I came up with the following insights:

  1. The Kerberos specific EncryptMessage() function does not provide message integrity, regardless of how the Securitycontext was initialized.

    • The general EncryptMessage() and general DecryptMessage functions support the feature of creating and verifying the message's integrity because there exists some supporting Security Support Providers (SSPs) - but Kerberos does not.

    • If DecryptMessage would check the message's integrity, there must be a respective error return code in case of a modified message. The general DecryptMessage interface lists the error code "SEC_E_MESSAGE_ALTERED" which is described as "The message has been altered. Used with the Digest and Schannel SSPs.".

    • The specific DecryptMessage interface for the SSPs Digest and Schannel lists the SEC_E_MESSAGE_ALTERED - but the Kerberos DecryptMessage does not.

    • Within the parameter description of the general EncryptMessage's documentation, the term 'signature' is used only regarding the Digest SSP: "When using the Digest SSP, there must be a second buffer of type SECBUFFER_PADDING or SEC_BUFFER_DATA to hold signature information".

  2. MakeSignature does not create a digital signature according to Wikipedia's definition (authenticity + non-repudiation + integrity). MakeSignature creates a cryptographic hash to provide message integrity.

    • The name of the MakeSignature() function leads to the idea that SSPI creates a digital signature (authenticity + non-repudiation + integrity) but the MakeSignature documentation explains that only a cryptographic checksum is created (providing integrity): "The MakeSignature function generates a cryptographic checksum of the message, and also includes sequencing information to prevent message loss or insertion."

    • The VerifySignature documentation helps as well to clarify SSPI's terminology: "Verifies that a message signed by using the MakeSignature function was received in the correct sequence and has not been modified."

  3. From (1) and (2) it follows that one needs to invoke EncryptData() and afterwards MakeSignature() (for the ciphertext) to achieve confidentiality and integrity.

Hope that my self-answer will help someone at some point in time ;)

If someone has something to add or correct in my answer, please reply and help to improve the information collected here!

chrobs
  • 389
  • 1
  • 3
  • 8

2 Answers2

0

If I remember correctly you only call EncryptMessage/DecryptMessage and this will do the signing too, if the negotiated context requires it. For example if you look at SSPI/Kerberos Interoperability with GSSAPI it states that EncryptMessagepairs with GSS_Unwrap and DecryptMessage pairs with GSS_Wrap, without involving MakeSignature. The example in the link also shows that you must supply 3 SecBuffer structures (SECBUFFER_TOKEN, SECBUFFER_DATA and SECBUFFER_PADDING, the last I think is optional) to EncryptMessage and 2 for DecryptMessage. The two complementary examples at Using SSPI with a Windows Sockets Server and Using SSPI with a Windows Sockets Client give full functional message exchange and you can also see that MakeSignature/VerifySignature are never called, the signature is handled by Encrypt/Decrypt and is placed in the 'security token' header or trailer (where to it goes on the wire is not specified by SSPI/SPNego/Kerberos, this is not TLS/Schannel...).

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
0

If you want to create a GSS Wrap token with only a signature (not encrypted), pass KERB_WRAP_NO_ENCRYPT as the qop value to EncryptMessage. The signed wrap token includes the payload and the signature.

MakeSignature creates a GSS MIC token - which is only the signature and does not include the payload. You can use this with application protocols that require a detached signature.

Roman Zh.
  • 985
  • 2
  • 6
  • 20