Plan 9 from Bell Labs’s /usr/web/sources/contrib/ericvh/go-plan9/src/pkg/crypto/tls/handshake_messages.go

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


// 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:];
	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:];
	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:];
		certsLen -= 3 + certLen;
		numCerts++;
	}

	m.certificates = make([][]byte, numCerts);
	d = data[7:];
	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:];
	}

	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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.