3.3.4.2.1 Generating a Client Netlogon Signature Token

If AES is negotiated, a client generates an NL_AUTH_SHA2_SIGNATURE token (section 2.2.1.3.3) that contains an HMAC-SHA256 checksum [RFC4634], a sequence number, and a Confounder (if confidentiality has been requested) to send data protected on the wire. The data is encrypted using the AES algorithm. If AES is not negotiated, a client generates a Netlogon Signature token that contains an HMAC-MD5 checksum ([RFC2104]), a sequence number, and a Confounder (if confidentiality has been requested) to send data protected on the wire. The data is encrypted using the negotiated encryption algorithm. Note that in the algorithm that follows, the term Confidentiality is used as defined in section 3.3.1. The following steps are performed to generate the client Netlogon Signature tokens and to encrypt the data if requested.

  1. If AES is negotiated:

    • The SignatureAlgorithm first byte MUST be set to 0x13, and the second byte MUST be set to 0x00.

    • If the Confidentiality option (section 3.3.1) is requested from the application, then the SealAlgorithm first byte MUST be set to 0x1A, the second byte MUST be set to 0x00, and the Confounder MUST be filled with cryptographically random data.

    • If the Confidentiality option (section 3.3.1) is not requested, then the SealAlgorithm MUST be filled with two bytes of 0xff and the Confounder is not included in the token.

  2. If AES is not negotiated:

    • The SignatureAlgorithm first byte MUST be set to 0x77, and the second byte MUST be set to 0x00.

    • If the Confidentiality option (section 3.3.1) is requested from the application, then the SealAlgorithm first byte MUST be set to 0x7A, the second byte MUST be set to 0x00, and the Confounder MUST be filled with cryptographically random data.

    • If the Confidentiality option is not requested, then the SealAlgorithm MUST be filled with two bytes of value 0xff and the Confounder is not included in the token.

  3. The Pad MUST be filled with 0xff bytes.

  4. The Flags MUST be filled with 0x00 bytes.

  5. The SequenceNumber is 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, ClientSequenceNumber.LowPart)
              SET CopySeqNumber[1] to byte(2, ClientSequenceNumber.LowPart)
              SET CopySeqNumber[2] to byte(1, ClientSequenceNumber.LowPart)
              SET CopySeqNumber[3] to byte(0, ClientSequenceNumber.LowPart)
              SET CopySeqNumber[4] to byte(3, ClientSequenceNumber.HighPart)
              SET CopySeqNumber[5] to byte(2, ClientSequenceNumber.HighPart)
              SET CopySeqNumber[6] to byte(1, ClientSequenceNumber.HighPart)
              SET CopySeqNumber[7] to byte(0, ClientSequenceNumber.HighPart)
              Set CopySeqNumber[4] to CopySeqNumber[4] OR 0x80
    
  6. The ClientSequenceNumber MUST be incremented by 1.

  7. 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 bytes]);
     IF Confidentiality requested
     CALL SHA256Input(HashContext, Confounder, [8 bytes]);
      
     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 bytes])
     CALL MD5Update(md5context, NL_AUTH_SIGNATURE, [8 bytes])
     IF Confidentiality requested
          CALL MD5Update(md5context, Confounder, [8 bytes])
     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.

    After the signature is computed, the signature MUST be truncated, with only the first 8 bytes being copied into the Checksum field of NL_AUTH_SHA2_SIGNATURE structure (section 2.2.1.3.3) if AES is negotiated, otherwise, into the Checksum field of NL_AUTH_SIGNATURE structure (section 2.2.1.3.2).

  8. If the Confidentiality option is requested, the Confounder field and the data MUST be encrypted, in that order, using the same encryption algorithm.

    • If AES is negotiated, then the server MUST use AES-128 for encryption. The server MUST derive the AES key using the following algorithm:

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

      The server MUST encrypt the Confounder field using the initialization vector constructed by concatenating the sequence number with itself twice (thus getting 16 bytes of data). For encrypting the data, the initialization vector MUST be constructed using the last block of the encrypted Confounder field.

    • Else, the server MUST use RC4 for encryption. The server MUST derive the RC4 key 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 bytes], XorKey, size of XorKey, TmpData)
       CALL hmac_md5(CopySeqNumber, size of CopySeqNumber, TmpData, 
                     size of TmpData, EncryptionKey)
      

      The hmac_md5 function is defined in the Appendix of [RFC2104]. The server MUST use this key to initialize RC4 and encrypt the Confounder field and then the data. The server MUST initialize RC4 only once, before encrypting the Confounder field.

  9. The SequenceNumber MUST be encrypted. If AES is negotiated, then the AES-128 algorithm MUST be used, using the SessionKey with an initialization vector constructed by concatenating the first 8 bytes of the checksum with itself twice (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 bytes], SessionKey, size of SessionKey, TmpData)
     CALL hmac_md5(Checksum, size of Checksum, TmpData, size of TmpData, 
                   EncryptionKey)
    

    The NetLogon Signature token MUST then be sent to the server along with the data.