| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package tls |
| |
| type clientHelloMsg struct { |
| raw []byte; |
| major, minor uint8; |
| random []byte; |
| sessionId []byte; |
| cipherSuites []uint16; |
| compressionMethods []uint8; |
| } |
| |
| func (m *clientHelloMsg) marshal() []byte { |
| if m.raw != nil { |
| return m.raw |
| } |
| |
| length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods); |
| x := make([]byte, 4+length); |
| x[0] = typeClientHello; |
| x[1] = uint8(length >> 16); |
| x[2] = uint8(length >> 8); |
| x[3] = uint8(length); |
| x[4] = m.major; |
| x[5] = m.minor; |
| copy(x[6:38], m.random); |
| x[38] = uint8(len(m.sessionId)); |
| copy(x[39:39+len(m.sessionId)], m.sessionId); |
| y := x[39+len(m.sessionId):]; |
| y[0] = uint8(len(m.cipherSuites) >> 7); |
| y[1] = uint8(len(m.cipherSuites) << 1); |
| for i, suite := range m.cipherSuites { |
| y[2+i*2] = uint8(suite >> 8); |
| y[3+i*2] = uint8(suite); |
| } |
| z := y[2+len(m.cipherSuites)*2:]; |
| z[0] = uint8(len(m.compressionMethods)); |
| copy(z[1:], m.compressionMethods); |
| m.raw = x; |
| |
| return x; |
| } |
| |
| func (m *clientHelloMsg) unmarshal(data []byte) bool { |
| if len(data) < 43 { |
| return false |
| } |
| m.raw = data; |
| m.major = data[4]; |
| m.minor = data[5]; |
| m.random = data[6:38]; |
| sessionIdLen := int(data[38]); |
| if sessionIdLen > 32 || len(data) < 39+sessionIdLen { |
| return false |
| } |
| m.sessionId = data[39 : 39+sessionIdLen]; |
| data = data[39+sessionIdLen:]; |
| if len(data) < 2 { |
| return false |
| } |
| // cipherSuiteLen is the number of bytes of cipher suite numbers. Since |
| // they are uint16s, the number must be even. |
| cipherSuiteLen := int(data[0])<<8 | int(data[1]); |
| if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen { |
| return false |
| } |
| numCipherSuites := cipherSuiteLen / 2; |
| m.cipherSuites = make([]uint16, numCipherSuites); |
| for i := 0; i < numCipherSuites; i++ { |
| m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i]) |
| } |
| data = data[2+cipherSuiteLen:]; |
| if len(data) < 2 { |
| return false |
| } |
| compressionMethodsLen := int(data[0]); |
| if len(data) < 1+compressionMethodsLen { |
| return false |
| } |
| m.compressionMethods = data[1 : 1+compressionMethodsLen]; |
| |
| // A ClientHello may be following by trailing data: RFC 4346 section 7.4.1.2 |
| return true; |
| } |
| |
| type serverHelloMsg struct { |
| raw []byte; |
| major, minor uint8; |
| random []byte; |
| sessionId []byte; |
| cipherSuite uint16; |
| compressionMethod uint8; |
| } |
| |
| func (m *serverHelloMsg) marshal() []byte { |
| if m.raw != nil { |
| return m.raw |
| } |
| |
| length := 38 + len(m.sessionId); |
| x := make([]byte, 4+length); |
| x[0] = typeServerHello; |
| x[1] = uint8(length >> 16); |
| x[2] = uint8(length >> 8); |
| x[3] = uint8(length); |
| x[4] = m.major; |
| x[5] = m.minor; |
| copy(x[6:38], m.random); |
| x[38] = uint8(len(m.sessionId)); |
| copy(x[39:39+len(m.sessionId)], m.sessionId); |
| z := x[39+len(m.sessionId):]; |
| z[0] = uint8(m.cipherSuite >> 8); |
| z[1] = uint8(m.cipherSuite); |
| z[2] = uint8(m.compressionMethod); |
| m.raw = x; |
| |
| return x; |
| } |
| |
| func (m *serverHelloMsg) unmarshal(data []byte) bool { |
| if len(data) < 42 { |
| return false |
| } |
| m.raw = data; |
| m.major = data[4]; |
| m.minor = data[5]; |
| m.random = data[6:38]; |
| sessionIdLen := int(data[38]); |
| if sessionIdLen > 32 || len(data) < 39+sessionIdLen { |
| return false |
| } |
| m.sessionId = data[39 : 39+sessionIdLen]; |
| data = data[39+sessionIdLen : len(data)]; |
| if len(data) < 3 { |
| return false |
| } |
| m.cipherSuite = uint16(data[0])<<8 | uint16(data[1]); |
| m.compressionMethod = data[2]; |
| |
| // Trailing data is allowed because extensions may be present. |
| return true; |
| } |
| |
| type certificateMsg struct { |
| raw []byte; |
| certificates [][]byte; |
| } |
| |
| func (m *certificateMsg) marshal() (x []byte) { |
| if m.raw != nil { |
| return m.raw |
| } |
| |
| var i int; |
| for _, slice := range m.certificates { |
| i += len(slice) |
| } |
| |
| length := 3 + 3*len(m.certificates) + i; |
| x = make([]byte, 4+length); |
| x[0] = typeCertificate; |
| x[1] = uint8(length >> 16); |
| x[2] = uint8(length >> 8); |
| x[3] = uint8(length); |
| |
| certificateOctets := length - 3; |
| x[4] = uint8(certificateOctets >> 16); |
| x[5] = uint8(certificateOctets >> 8); |
| x[6] = uint8(certificateOctets); |
| |
| y := x[7:]; |
| for _, slice := range m.certificates { |
| y[0] = uint8(len(slice) >> 16); |
| y[1] = uint8(len(slice) >> 8); |
| y[2] = uint8(len(slice)); |
| copy(y[3:], slice); |
| y = y[3+len(slice):]; |
| } |
| |
| m.raw = x; |
| return; |
| } |
| |
| func (m *certificateMsg) unmarshal(data []byte) bool { |
| if len(data) < 7 { |
| return false |
| } |
| |
| m.raw = data; |
| certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]); |
| if uint32(len(data)) != certsLen+7 { |
| return false |
| } |
| |
| numCerts := 0; |
| d := data[7:len(data)]; |
| for certsLen > 0 { |
| if len(d) < 4 { |
| return false |
| } |
| certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2]); |
| if uint32(len(d)) < 3+certLen { |
| return false |
| } |
| d = d[3+certLen : len(d)]; |
| certsLen -= 3 + certLen; |
| numCerts++; |
| } |
| |
| m.certificates = make([][]byte, numCerts); |
| d = data[7:len(data)]; |
| for i := 0; i < numCerts; i++ { |
| certLen := uint32(d[0])<<24 | uint32(d[1])<<8 | uint32(d[2]); |
| m.certificates[i] = d[3 : 3+certLen]; |
| d = d[3+certLen : len(d)]; |
| } |
| |
| return true; |
| } |
| |
| type serverHelloDoneMsg struct{} |
| |
| func (m *serverHelloDoneMsg) marshal() []byte { |
| x := make([]byte, 4); |
| x[0] = typeServerHelloDone; |
| return x; |
| } |
| |
| func (m *serverHelloDoneMsg) unmarshal(data []byte) bool { |
| return len(data) == 4 |
| } |
| |
| type clientKeyExchangeMsg struct { |
| raw []byte; |
| ciphertext []byte; |
| } |
| |
| func (m *clientKeyExchangeMsg) marshal() []byte { |
| if m.raw != nil { |
| return m.raw |
| } |
| length := len(m.ciphertext) + 2; |
| x := make([]byte, length+4); |
| x[0] = typeClientKeyExchange; |
| x[1] = uint8(length >> 16); |
| x[2] = uint8(length >> 8); |
| x[3] = uint8(length); |
| x[4] = uint8(len(m.ciphertext) >> 8); |
| x[5] = uint8(len(m.ciphertext)); |
| copy(x[6:], m.ciphertext); |
| |
| m.raw = x; |
| return x; |
| } |
| |
| func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool { |
| m.raw = data; |
| if len(data) < 7 { |
| return false |
| } |
| cipherTextLen := int(data[4])<<8 | int(data[5]); |
| if len(data) != 6+cipherTextLen { |
| return false |
| } |
| m.ciphertext = data[6:]; |
| return true; |
| } |
| |
| type finishedMsg struct { |
| raw []byte; |
| verifyData []byte; |
| } |
| |
| func (m *finishedMsg) marshal() (x []byte) { |
| if m.raw != nil { |
| return m.raw |
| } |
| |
| x = make([]byte, 16); |
| x[0] = typeFinished; |
| x[3] = 12; |
| copy(x[4:], m.verifyData); |
| m.raw = x; |
| return; |
| } |
| |
| func (m *finishedMsg) unmarshal(data []byte) bool { |
| m.raw = data; |
| if len(data) != 4+12 { |
| return false |
| } |
| m.verifyData = data[4:]; |
| return true; |
| } |