3.3.4.2.2 Receiving a Client Netlogon Signature Token

When a server receives encrypted data, it verifies the Netlogon Signature token. If AES is negotiated, a server receives an NL_AUTH_SHA2_SIGNATURE structure, otherwise it receives an NL_AUTH_SIGNATURE structure. The following steps are performed to verify the data  and to decrypt with AES if negotiated, otherwise RC4 if required:

  1. The SignatureAlgorithm bytes MUST be verified to ensure:

    • If AES is negotiated, the first byte is set to 0x13; otherwise the first byte is set to 0x77.

    • The second byte is set to 0x00.

    If either of these two is incorrect, an SEC_E_MESSAGE_ALTERED (0x8009030F) MUST be returned.

  2. If the Confidentiality option is requested from the application, then the SealAlgorithm MUST be verified to ensure that if AES is negotiated, the first byte is set to 0x1A; otherwise the first byte is set to 0x7A. The second byte is set to 0x00.

    If the Confidentiality option is not requested, then the SealAlgorithm MUST be verified to contain all 0xff bytes.

    If either of these two is incorrect, an SEC_E_MESSAGE_ALTERED (0x8009030F) MUST be returned.

  3. The Pad MUST be verified to contain all 0xff bytes and SEC_E_MESSAGE_ALTERED (0x8009030F) MUST be returned otherwise.

  4. The Flags data SHOULD<86> be disregarded.

  5. The SequenceNumber MUST be decrypted. If AES is negotiated, then the AES-128 algorithm MUST be used with Session Key and an initialization vector constructed by concatenating the checksum with itself (thus getting 16 bytes of data). Otherwise, the RC4 algorithm MUST be used. The RC4 key MUST be derived as follows:

     SET zeroes to 4 bytes of 0
      
     CALL hmac_md5(zeroes, 4, SessionKey, size of SessionKey, TmpData)
     CALL hmac_md5(Checksum, size of Checksum, TmpData, size of TmpData, 
                   DecryptionKey)
    
  6. A local copy of SequenceNumber MUST be computed using the following algorithm.

    Assume byte(n, l) returns byte n of the 32-bit number l.  The n parameter is limited to 0..3.  The least significant byte is 0, the most significant byte is 3.

     SET CopySeqNumber[0] to byte(3, ServerSequenceNumber.LowPart)
     SET CopySeqNumber[1] to byte(2, ServerSequenceNumber.LowPart)
     SET CopySeqNumber[2] to byte(1, ServerSequenceNumber.LowPart)
     SET CopySeqNumber[3] to byte(0, ServerSequenceNumber.LowPart)
      
     SET CopySeqNumber[4] to byte(3, ServerSequenceNumber.HighPart)
     SET CopySeqNumber[5] to byte(2, ServerSequenceNumber.HighPart)
     SET CopySeqNumber[6] to byte(1, ServerSequenceNumber.HighPart)
     SET CopySeqNumber[7] to byte(0, ServerSequenceNumber.HighPart)
     Set CopySeqNumber[4] to CopySeqNumber[4] OR 0x80
    
  7. The SequenceNumber MUST be compared to CopySeqNumber. If these two do not match, SEC_E_OUT_OF_SEQUENCE ([MS-ERREF] section 2.1.1) MUST be returned.<87>

  8. ServerSequenceNumber MUST be incremented.

    If the Confidentiality option is requested, the Confounder and the data MUST be decrypted using RC4.

  9. If the Confidentiality option is requested, the Confounder and the data MUST be decrypted.

    • The AES key used MUST be derived using the following algorithm:

       FOR (I=0; I < Key Length; I++)
       EncryptionKey [I] = SessionKey[I] XOR 0xf0 
      

    If AES is negotiated, decrypt using an initialization vector constructed by concatenating twice the sequence number (thus getting 16 bytes of data).

    • The RC4 key used MUST be derived using the following algorithm:

       SET zeroes to 4 bytes of 0
        
       FOR (I=0; I < Key Length; I++)
            XorKey [I] = SessionKey[I] XOR 0xf0
       CALL hmac_md5(zeroes, 4, XorKey, size of XorKey, TmpData)
       CALL hmac_md5(CopySeqNumber, size of CopySeqNumber, TmpData, 
                     size of TmpData, EncryptionKey)
      

      The hmac_md5 function is specified in [RFC2104].

  10. If AES is negotiated, then a signature MUST be computed using the following algorithm:

     CALL SHA256Reset(&HashContext, Sk, sizeof(Sk));
     CALL SHA256Input(HashContext, NL_AUTH_SHA2_SIGNATURE, 8);
     IF Confidentiality requested
          CALL SHA256Input(HashContext, Confounder, 8);
     CALL SHA256FinalBits(HashContext, Message, size of Message);
     CALL SHA256Result(HashContext, output);
     SET Signature to output
    

    Note: In the first call to SHA256Input only the first 8-bytes of the NL_AUTH_SHA2_SIGNATURE structure are used.

    Else a signature MUST be computed using the following algorithm:

     SET zeroes to 4 bytes of 0
      
     CALL MD5Init(md5context)
     CALL MD5Update(md5context, zeroes, 4)
     CALL MD5Update(md5context, NL_AUTH_SIGNATURE, 8)
     IF Confidentiality requested
        CALL MD5Update(md5context, Confounder, 8)
     CALL MD5Update(md5context, Message, size of Message)
     CALL MD5Final(md5context)
     CALL HMAC_MD5(md5context.digest, md5context.digest length, 
                  Session Key, size of Session Key, output)
     SET Signature to output
    

    Note: In the second call to MD5Update only the first 8-bytes of the NL_AUTH_SIGNATURE structure are used.

  11. The first 8 bytes of the computed signature MUST be compared to the checksum. If these two do not match, the SEC_E_MESSAGE_ALTERED (0x8009030F) MUST be returned, indicating that the message was altered.