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 }