github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/go-ntlm/ntlm/signature.go (about)

     1  //Copyright 2013 Thomson Reuters Global Resources. BSD License please see License file for more information
     2  
     3  package ntlm
     4  
     5  import (
     6  	rc4P "crypto/rc4"
     7  	"encoding/binary"
     8  	"encoding/hex"
     9  	"fmt"
    10  )
    11  
    12  type NtlmsspMessageSignature struct {
    13  	ByteData []byte
    14  	// A 32-bit unsigned integer that contains the signature version. This field MUST be 0x00000001.
    15  	Version []byte
    16  	// A 4-byte array that contains the random pad for the message.
    17  	RandomPad []byte
    18  	// A 4-byte array that contains the checksum for the message.
    19  	CheckSum []byte
    20  	// A 32-bit unsigned integer that contains the NTLM sequence number for this application message.
    21  	SeqNum []byte
    22  }
    23  
    24  func (n *NtlmsspMessageSignature) String() string {
    25  	return fmt.Sprintf("NtlmsspMessageSignature: %s", hex.EncodeToString(n.Bytes()))
    26  }
    27  
    28  func (n *NtlmsspMessageSignature) Bytes() []byte {
    29  	if n.ByteData != nil {
    30  		return n.ByteData
    31  	} else {
    32  		return concat(n.Version, n.RandomPad, n.CheckSum, n.SeqNum)
    33  	}
    34  	return nil
    35  }
    36  
    37  // Define SEAL(Handle, SigningKey, SeqNum, Message) as
    38  func seal(negFlags uint32, handle *rc4P.Cipher, signingKey []byte, seqNum uint32, message []byte) (sealedMessage []byte, sig *NtlmsspMessageSignature) {
    39  	sealedMessage = rc4(handle, message)
    40  	sig = mac(negFlags, handle, signingKey, uint32(seqNum), message)
    41  	return
    42  }
    43  
    44  // Define SIGN(Handle, SigningKey, SeqNum, Message) as
    45  func sign(negFlags uint32, handle *rc4P.Cipher, signingKey []byte, seqNum uint32, message []byte) []byte {
    46  	return concat(message, mac(negFlags, handle, signingKey, uint32(seqNum), message).Bytes())
    47  }
    48  
    49  func mac(negFlags uint32, handle *rc4P.Cipher, signingKey []byte, seqNum uint32, message []byte) (result *NtlmsspMessageSignature) {
    50  	if NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(negFlags) {
    51  		result = macWithExtendedSessionSecurity(negFlags, handle, signingKey, seqNum, message)
    52  	} else {
    53  		result = macWithoutExtendedSessionSecurity(handle, seqNum, message)
    54  	}
    55  	return result
    56  }
    57  
    58  // Define MAC(Handle, SigningKey, SeqNum, Message) as
    59  // Set NTLMSSP_MESSAGE_SIGNATURE.Version to 0x00000001
    60  // Set NTLMSSP_MESSAGE_SIGNATURE.Checksum to CRC32(Message)
    61  // Set NTLMSSP_MESSAGE_SIGNATURE.RandomPad RC4(Handle, RandomPad)
    62  // Set NTLMSSP_MESSAGE_SIGNATURE.Checksum to RC4(Handle, NTLMSSP_MESSAGE_SIGNATURE.Checksum)
    63  // Set NTLMSSP_MESSAGE_SIGNATURE.SeqNum to RC4(Handle, 0x00000000)
    64  // If (connection oriented)
    65  //   Set NTLMSSP_MESSAGE_SIGNATURE.SeqNum to NTLMSSP_MESSAGE_SIGNATURE.SeqNum XOR SeqNum
    66  //   Set SeqNum to SeqNum + 1
    67  // Else
    68  //   Set NTLMSSP_MESSAGE_SIGNATURE.SeqNum to NTLMSSP_MESSAGE_SIGNATURE.SeqNum XOR (application supplied SeqNum)
    69  // EndIf
    70  // Set NTLMSSP_MESSAGE_SIGNATURE.RandomPad to 0
    71  // End
    72  func macWithoutExtendedSessionSecurity(handle *rc4P.Cipher, seqNum uint32, message []byte) *NtlmsspMessageSignature {
    73  	sig := new(NtlmsspMessageSignature)
    74  
    75  	seqNumBytes := make([]byte, 4)
    76  	binary.LittleEndian.PutUint32(seqNumBytes, seqNum)
    77  
    78  	sig.Version = []byte{0x01, 0x00, 0x00, 0x00}
    79  	sig.CheckSum = make([]byte, 4)
    80  	binary.LittleEndian.PutUint32(sig.CheckSum, crc32(message))
    81  	sig.RandomPad = rc4(handle, zeroBytes(4))
    82  	sig.CheckSum = rc4(handle, sig.CheckSum)
    83  	sig.SeqNum = rc4(handle, zeroBytes(4))
    84  	for i := 0; i < 4; i++ {
    85  		sig.SeqNum[i] = sig.SeqNum[i] ^ seqNumBytes[i]
    86  	}
    87  	sig.RandomPad = zeroBytes(4)
    88  	return sig
    89  }
    90  
    91  // Define MAC(Handle, SigningKey, SeqNum, Message) as
    92  // Set NTLMSSP_MESSAGE_SIGNATURE.Version to 0x00000001
    93  // if Key Exchange Key Negotiated
    94  //   Set NTLMSSP_MESSAGE_SIGNATURE.Checksum to RC4(Handle, HMAC_MD5(SigningKey, ConcatenationOf(SeqNum, Message))[0..7])
    95  // else
    96  //   Set NTLMSSP_MESSAGE_SIGNATURE.Checksum to HMAC_MD5(SigningKey, ConcatenationOf(SeqNum, Message))[0..7]
    97  // end
    98  // Set NTLMSSP_MESSAGE_SIGNATURE.SeqNum to SeqNum
    99  // Set SeqNum to SeqNum + 1
   100  // EndDefine
   101  func macWithExtendedSessionSecurity(negFlags uint32, handle *rc4P.Cipher, signingKey []byte, seqNum uint32, message []byte) *NtlmsspMessageSignature {
   102  	sig := new(NtlmsspMessageSignature)
   103  	sig.Version = []byte{0x01, 0x00, 0x00, 0x00}
   104  	seqNumBytes := make([]byte, 4)
   105  	binary.LittleEndian.PutUint32(seqNumBytes, seqNum)
   106  	sig.CheckSum = hmacMd5(signingKey, concat(seqNumBytes, message))[0:8]
   107  	if NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(negFlags) {
   108  		sig.CheckSum = rc4(handle, sig.CheckSum)
   109  	}
   110  	sig.SeqNum = seqNumBytes
   111  	return sig
   112  }
   113  
   114  func reinitSealingKey(key []byte, sequenceNumber int) (handle *rc4P.Cipher, err error) {
   115  	seqNumBytes := make([]byte, 4)
   116  	binary.LittleEndian.PutUint32(seqNumBytes, uint32(sequenceNumber))
   117  	newKey := md5(concat(key, seqNumBytes))
   118  	handle, err = rc4Init(newKey)
   119  	return handle, err
   120  }