ソースを参照

1) Change default gofmt default settings for

parsing and printing to new syntax.

                  Use -oldparser to parse the old syntax,
                  use -oldprinter to print the old syntax.

               2) Change default gofmt formatting settings
                  to use tabs for indentation only and to use
                  spaces for alignment. This will make the code
                  alignment insensitive to an editor's tabwidth.

                  Use -spaces=false to use tabs for alignment.

               3) Manually changed src/exp/parser/parser_test.go
                  so that it doesn't try to parse the parser's
                  source files using the old syntax (they have
                  new syntax now).

               4) gofmt -w src misc test/bench

	       1st set of files.

R=rsc
CC=agl, golang-dev, iant, ken2, r
https://golang.org/cl/180047
tls13
Robert Griesemer 15年前
コミット
536df07f72
16個のファイルの変更1018行の追加1018行の削除
  1. +26
    -26
      alert.go
  2. +12
    -12
      ca_set.go
  3. +43
    -43
      common.go
  4. +111
    -111
      handshake_client.go
  5. +142
    -142
      handshake_messages.go
  6. +54
    -54
      handshake_messages_test.go
  7. +108
    -108
      handshake_server.go
  8. +81
    -81
      handshake_server_test.go
  9. +73
    -73
      prf.go
  10. +22
    -22
      prf_test.go
  11. +108
    -108
      record_process.go
  12. +73
    -73
      record_process_test.go
  13. +10
    -10
      record_read.go
  14. +19
    -19
      record_read_test.go
  15. +66
    -66
      record_write.go
  16. +70
    -70
      tls.go

+ 26
- 26
alert.go ファイルの表示

@@ -8,36 +8,36 @@ type alertLevel int
type alertType int

const (
alertLevelWarning alertLevel = 1;
alertLevelError alertLevel = 2;
alertLevelWarning alertLevel = 1
alertLevelError alertLevel = 2
)

const (
alertCloseNotify alertType = 0;
alertUnexpectedMessage alertType = 10;
alertBadRecordMAC alertType = 20;
alertDecryptionFailed alertType = 21;
alertRecordOverflow alertType = 22;
alertDecompressionFailure alertType = 30;
alertHandshakeFailure alertType = 40;
alertBadCertificate alertType = 42;
alertUnsupportedCertificate alertType = 43;
alertCertificateRevoked alertType = 44;
alertCertificateExpired alertType = 45;
alertCertificateUnknown alertType = 46;
alertIllegalParameter alertType = 47;
alertUnknownCA alertType = 48;
alertAccessDenied alertType = 49;
alertDecodeError alertType = 50;
alertDecryptError alertType = 51;
alertProtocolVersion alertType = 70;
alertInsufficientSecurity alertType = 71;
alertInternalError alertType = 80;
alertUserCanceled alertType = 90;
alertNoRenegotiation alertType = 100;
alertCloseNotify alertType = 0
alertUnexpectedMessage alertType = 10
alertBadRecordMAC alertType = 20
alertDecryptionFailed alertType = 21
alertRecordOverflow alertType = 22
alertDecompressionFailure alertType = 30
alertHandshakeFailure alertType = 40
alertBadCertificate alertType = 42
alertUnsupportedCertificate alertType = 43
alertCertificateRevoked alertType = 44
alertCertificateExpired alertType = 45
alertCertificateUnknown alertType = 46
alertIllegalParameter alertType = 47
alertUnknownCA alertType = 48
alertAccessDenied alertType = 49
alertDecodeError alertType = 50
alertDecryptError alertType = 51
alertProtocolVersion alertType = 70
alertInsufficientSecurity alertType = 71
alertInternalError alertType = 80
alertUserCanceled alertType = 90
alertNoRenegotiation alertType = 100
)

type alert struct {
level alertLevel;
error alertType;
level alertLevel
error alertType
}

+ 12
- 12
ca_set.go ファイルの表示

@@ -5,14 +5,14 @@
package tls

import (
"crypto/x509";
"encoding/pem";
"crypto/x509"
"encoding/pem"
)

// A CASet is a set of certificates.
type CASet struct {
bySubjectKeyId map[string]*x509.Certificate;
byName map[string]*x509.Certificate;
bySubjectKeyId map[string]*x509.Certificate
byName map[string]*x509.Certificate
}

func NewCASet() *CASet {
@@ -29,7 +29,7 @@ func nameToKey(name *x509.Name) string {
// FindParent attempts to find the certificate in s which signs the given
// certificate. If no such certificate can be found, it returns nil.
func (s *CASet) FindParent(cert *x509.Certificate) (parent *x509.Certificate) {
var ok bool;
var ok bool

if len(cert.AuthorityKeyId) > 0 {
parent, ok = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
@@ -40,7 +40,7 @@ func (s *CASet) FindParent(cert *x509.Certificate) (parent *x509.Certificate) {
if !ok {
return nil
}
return parent;
return parent
}

// SetFromPEM attempts to parse a series of PEM encoded root certificates. It
@@ -50,8 +50,8 @@ func (s *CASet) FindParent(cert *x509.Certificate) (parent *x509.Certificate) {
// function.
func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
for len(pemCerts) > 0 {
var block *pem.Block;
block, pemCerts = pem.Decode(pemCerts);
var block *pem.Block
block, pemCerts = pem.Decode(pemCerts)
if block == nil {
break
}
@@ -59,7 +59,7 @@ func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
continue
}

cert, err := x509.ParseCertificate(block.Bytes);
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
continue
}
@@ -67,9 +67,9 @@ func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) {
if len(cert.SubjectKeyId) > 0 {
s.bySubjectKeyId[string(cert.SubjectKeyId)] = cert
}
s.byName[nameToKey(&cert.Subject)] = cert;
ok = true;
s.byName[nameToKey(&cert.Subject)] = cert
ok = true
}

return;
return
}

+ 43
- 43
common.go ファイルの表示

@@ -5,21 +5,21 @@
package tls

import (
"crypto/rsa";
"io";
"os";
"crypto/rsa"
"io"
"os"
)

const (
// maxTLSCiphertext is the maximum length of a plaintext payload.
maxTLSPlaintext = 16384;
maxTLSPlaintext = 16384
// maxTLSCiphertext is the maximum length payload after compression and encryption.
maxTLSCiphertext = 16384 + 2048;
maxTLSCiphertext = 16384 + 2048
// maxHandshakeMsg is the largest single handshake message that we'll buffer.
maxHandshakeMsg = 65536;
maxHandshakeMsg = 65536
// defaultMajor and defaultMinor are the maximum TLS version that we support.
defaultMajor = 3;
defaultMinor = 2;
defaultMajor = 3
defaultMinor = 2
)


@@ -27,68 +27,68 @@ const (
type recordType uint8

const (
recordTypeChangeCipherSpec recordType = 20;
recordTypeAlert recordType = 21;
recordTypeHandshake recordType = 22;
recordTypeApplicationData recordType = 23;
recordTypeChangeCipherSpec recordType = 20
recordTypeAlert recordType = 21
recordTypeHandshake recordType = 22
recordTypeApplicationData recordType = 23
)

// TLS handshake message types.
const (
typeClientHello uint8 = 1;
typeServerHello uint8 = 2;
typeCertificate uint8 = 11;
typeServerHelloDone uint8 = 14;
typeClientKeyExchange uint8 = 16;
typeFinished uint8 = 20;
typeClientHello uint8 = 1
typeServerHello uint8 = 2
typeCertificate uint8 = 11
typeServerHelloDone uint8 = 14
typeClientKeyExchange uint8 = 16
typeFinished uint8 = 20
)

// TLS cipher suites.
var (
TLS_RSA_WITH_RC4_128_SHA uint16 = 5;
TLS_RSA_WITH_RC4_128_SHA uint16 = 5
)

// TLS compression types.
var (
compressionNone uint8 = 0;
compressionNone uint8 = 0
)

type ConnectionState struct {
HandshakeComplete bool;
CipherSuite string;
Error alertType;
HandshakeComplete bool
CipherSuite string
Error alertType
}

// A Config structure is used to configure a TLS client or server. After one
// has been passed to a TLS function it must not be modified.
type Config struct {
// Rand provides the source of entropy for nonces and RSA blinding.
Rand io.Reader;
Rand io.Reader
// Time returns the current time as the number of seconds since the epoch.
Time func() int64;
Certificates []Certificate;
RootCAs *CASet;
Time func() int64
Certificates []Certificate
RootCAs *CASet
}

type Certificate struct {
Certificate [][]byte;
PrivateKey *rsa.PrivateKey;
Certificate [][]byte
PrivateKey *rsa.PrivateKey
}

// A TLS record.
type record struct {
contentType recordType;
major, minor uint8;
payload []byte;
contentType recordType
major, minor uint8
payload []byte
}

type handshakeMessage interface {
marshal() []byte;
marshal() []byte
}

type encryptor interface {
// XORKeyStream xors the contents of the slice with bytes from the key stream.
XORKeyStream(buf []byte);
XORKeyStream(buf []byte)
}

// mutualVersion returns the protocol version to use given the advertised
@@ -98,24 +98,24 @@ func mutualVersion(theirMajor, theirMinor uint8) (major, minor uint8, ok bool) {
if theirMajor < 3 || theirMajor == 3 && theirMinor < 1 {
return 0, 0, false
}
major = 3;
minor = 2;
major = 3
minor = 2
if theirMinor < minor {
minor = theirMinor
}
ok = true;
return;
ok = true
return
}

// A nop implements the NULL encryption and MAC algorithms.
type nop struct{}

func (nop) XORKeyStream(buf []byte) {}
func (nop) XORKeyStream(buf []byte) {}

func (nop) Write(buf []byte) (int, os.Error) { return len(buf), nil }
func (nop) Write(buf []byte) (int, os.Error) { return len(buf), nil }

func (nop) Sum() []byte { return nil }
func (nop) Sum() []byte { return nil }

func (nop) Reset() {}
func (nop) Reset() {}

func (nop) Size() int { return 0 }
func (nop) Size() int { return 0 }

+ 111
- 111
handshake_client.go ファイルの表示

@@ -5,33 +5,33 @@
package tls

import (
"crypto/hmac";
"crypto/rc4";
"crypto/rsa";
"crypto/sha1";
"crypto/subtle";
"crypto/x509";
"io";
"crypto/hmac"
"crypto/rc4"
"crypto/rsa"
"crypto/sha1"
"crypto/subtle"
"crypto/x509"
"io"
)

// A serverHandshake performs the server side of the TLS 1.1 handshake protocol.
type clientHandshake struct {
writeChan chan<- interface{};
controlChan chan<- interface{};
msgChan <-chan interface{};
config *Config;
writeChan chan<- interface{}
controlChan chan<- interface{}
msgChan <-chan interface{}
config *Config
}

func (h *clientHandshake) loop(writeChan chan<- interface{}, controlChan chan<- interface{}, msgChan <-chan interface{}, config *Config) {
h.writeChan = writeChan;
h.controlChan = controlChan;
h.msgChan = msgChan;
h.config = config;
h.writeChan = writeChan
h.controlChan = controlChan
h.msgChan = msgChan
h.config = config

defer close(writeChan);
defer close(controlChan);
defer close(writeChan)
defer close(controlChan)

finishedHash := newFinishedHash();
finishedHash := newFinishedHash()

hello := &clientHelloMsg{
major: defaultMajor,
@@ -39,175 +39,175 @@ func (h *clientHandshake) loop(writeChan chan<- interface{}, controlChan chan<-
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
random: make([]byte, 32),
};
currentTime := uint32(config.Time());
hello.random[0] = byte(currentTime >> 24);
hello.random[1] = byte(currentTime >> 16);
hello.random[2] = byte(currentTime >> 8);
hello.random[3] = byte(currentTime);
_, err := io.ReadFull(config.Rand, hello.random[4:]);
}
currentTime := uint32(config.Time())
hello.random[0] = byte(currentTime >> 24)
hello.random[1] = byte(currentTime >> 16)
hello.random[2] = byte(currentTime >> 8)
hello.random[3] = byte(currentTime)
_, err := io.ReadFull(config.Rand, hello.random[4:])
if err != nil {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}

finishedHash.Write(hello.marshal());
writeChan <- writerSetVersion{defaultMajor, defaultMinor};
writeChan <- hello;
finishedHash.Write(hello.marshal())
writeChan <- writerSetVersion{defaultMajor, defaultMinor}
writeChan <- hello

serverHello, ok := h.readHandshakeMsg().(*serverHelloMsg);
serverHello, ok := h.readHandshakeMsg().(*serverHelloMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
finishedHash.Write(serverHello.marshal());
major, minor, ok := mutualVersion(serverHello.major, serverHello.minor);
finishedHash.Write(serverHello.marshal())
major, minor, ok := mutualVersion(serverHello.major, serverHello.minor)
if !ok {
h.error(alertProtocolVersion);
return;
h.error(alertProtocolVersion)
return
}

writeChan <- writerSetVersion{major, minor};
writeChan <- writerSetVersion{major, minor}

if serverHello.cipherSuite != TLS_RSA_WITH_RC4_128_SHA ||
serverHello.compressionMethod != compressionNone {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}

certMsg, ok := h.readHandshakeMsg().(*certificateMsg);
certMsg, ok := h.readHandshakeMsg().(*certificateMsg)
if !ok || len(certMsg.certificates) == 0 {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
finishedHash.Write(certMsg.marshal());
finishedHash.Write(certMsg.marshal())

certs := make([]*x509.Certificate, len(certMsg.certificates));
certs := make([]*x509.Certificate, len(certMsg.certificates))
for i, asn1Data := range certMsg.certificates {
cert, err := x509.ParseCertificate(asn1Data);
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
h.error(alertBadCertificate);
return;
h.error(alertBadCertificate)
return
}
certs[i] = cert;
certs[i] = cert
}

// TODO(agl): do better validation of certs: max path length, name restrictions etc.
for i := 1; i < len(certs); i++ {
if certs[i-1].CheckSignatureFrom(certs[i]) != nil {
h.error(alertBadCertificate);
return;
h.error(alertBadCertificate)
return
}
}

if config.RootCAs != nil {
root := config.RootCAs.FindParent(certs[len(certs)-1]);
root := config.RootCAs.FindParent(certs[len(certs)-1])
if root == nil {
h.error(alertBadCertificate);
return;
h.error(alertBadCertificate)
return
}
if certs[len(certs)-1].CheckSignatureFrom(root) != nil {
h.error(alertBadCertificate);
return;
h.error(alertBadCertificate)
return
}
}

pub, ok := certs[0].PublicKey.(*rsa.PublicKey);
pub, ok := certs[0].PublicKey.(*rsa.PublicKey)
if !ok {
h.error(alertUnsupportedCertificate);
return;
h.error(alertUnsupportedCertificate)
return
}

shd, ok := h.readHandshakeMsg().(*serverHelloDoneMsg);
shd, ok := h.readHandshakeMsg().(*serverHelloDoneMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
finishedHash.Write(shd.marshal());
finishedHash.Write(shd.marshal())

ckx := new(clientKeyExchangeMsg);
preMasterSecret := make([]byte, 48);
ckx := new(clientKeyExchangeMsg)
preMasterSecret := make([]byte, 48)
// Note that the version number in the preMasterSecret must be the
// version offered in the ClientHello.
preMasterSecret[0] = defaultMajor;
preMasterSecret[1] = defaultMinor;
_, err = io.ReadFull(config.Rand, preMasterSecret[2:]);
preMasterSecret[0] = defaultMajor
preMasterSecret[1] = defaultMinor
_, err = io.ReadFull(config.Rand, preMasterSecret[2:])
if err != nil {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}

ckx.ciphertext, err = rsa.EncryptPKCS1v15(config.Rand, pub, preMasterSecret);
ckx.ciphertext, err = rsa.EncryptPKCS1v15(config.Rand, pub, preMasterSecret)
if err != nil {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}

finishedHash.Write(ckx.marshal());
writeChan <- ckx;
finishedHash.Write(ckx.marshal())
writeChan <- ckx

suite := cipherSuites[0];
suite := cipherSuites[0]
masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
keysFromPreMasterSecret11(preMasterSecret, hello.random, serverHello.random, suite.hashLength, suite.cipherKeyLength);
keysFromPreMasterSecret11(preMasterSecret, hello.random, serverHello.random, suite.hashLength, suite.cipherKeyLength)

cipher, _ := rc4.NewCipher(clientKey);
writeChan <- writerChangeCipherSpec{cipher, hmac.New(sha1.New(), clientMAC)};
cipher, _ := rc4.NewCipher(clientKey)
writeChan <- writerChangeCipherSpec{cipher, hmac.New(sha1.New(), clientMAC)}

finished := new(finishedMsg);
finished.verifyData = finishedHash.clientSum(masterSecret);
finishedHash.Write(finished.marshal());
writeChan <- finished;
finished := new(finishedMsg)
finished.verifyData = finishedHash.clientSum(masterSecret)
finishedHash.Write(finished.marshal())
writeChan <- finished

// TODO(agl): this is cut-through mode which should probably be an option.
writeChan <- writerEnableApplicationData{};
writeChan <- writerEnableApplicationData{}

_, ok = h.readHandshakeMsg().(changeCipherSpec);
_, ok = h.readHandshakeMsg().(changeCipherSpec)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}

cipher2, _ := rc4.NewCipher(serverKey);
controlChan <- &newCipherSpec{cipher2, hmac.New(sha1.New(), serverMAC)};
cipher2, _ := rc4.NewCipher(serverKey)
controlChan <- &newCipherSpec{cipher2, hmac.New(sha1.New(), serverMAC)}

serverFinished, ok := h.readHandshakeMsg().(*finishedMsg);
serverFinished, ok := h.readHandshakeMsg().(*finishedMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}

verify := finishedHash.serverSum(masterSecret);
verify := finishedHash.serverSum(masterSecret)
if len(verify) != len(serverFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
h.error(alertHandshakeFailure);
return;
h.error(alertHandshakeFailure)
return
}

controlChan <- ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0};
controlChan <- ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0}

// This should just block forever.
_ = h.readHandshakeMsg();
h.error(alertUnexpectedMessage);
return;
_ = h.readHandshakeMsg()
h.error(alertUnexpectedMessage)
return
}

func (h *clientHandshake) readHandshakeMsg() interface{} {
v := <-h.msgChan;
v := <-h.msgChan
if closed(h.msgChan) {
// If the channel closed then the processor received an error
// from the peer and we don't want to echo it back to them.
h.msgChan = nil;
return 0;
h.msgChan = nil
return 0
}
if _, ok := v.(alert); ok {
// We got an alert from the processor. We forward to the writer
// and shutdown.
h.writeChan <- v;
h.msgChan = nil;
return 0;
h.writeChan <- v
h.msgChan = nil
return 0
}
return v;
return v
}

func (h *clientHandshake) error(e alertType) {
@@ -217,9 +217,9 @@ func (h *clientHandshake) error(e alertType) {
go func() {
for _ = range h.msgChan {
}
}();
h.controlChan <- ConnectionState{false, "", e};
close(h.controlChan);
h.writeChan <- alert{alertLevelError, e};
}()
h.controlChan <- ConnectionState{false, "", e}
close(h.controlChan)
h.writeChan <- alert{alertLevelError, e}
}
}

+ 142
- 142
handshake_messages.go ファイルの表示

@@ -5,12 +5,12 @@
package tls

type clientHelloMsg struct {
raw []byte;
major, minor uint8;
random []byte;
sessionId []byte;
cipherSuites []uint16;
compressionMethods []uint8;
raw []byte
major, minor uint8
random []byte
sessionId []byte
cipherSuites []uint16
compressionMethods []uint8
}

func (m *clientHelloMsg) marshal() []byte {
@@ -18,81 +18,81 @@ func (m *clientHelloMsg) marshal() []byte {
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);
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);
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;
z := y[2+len(m.cipherSuites)*2:]
z[0] = uint8(len(m.compressionMethods))
copy(z[1:], m.compressionMethods)
m.raw = x

return 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]);
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:];
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]);
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);
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:];
data = data[2+cipherSuiteLen:]
if len(data) < 2 {
return false
}
compressionMethodsLen := int(data[0]);
compressionMethodsLen := int(data[0])
if len(data) < 1+compressionMethodsLen {
return false
}
m.compressionMethods = data[1 : 1+compressionMethodsLen];
m.compressionMethods = data[1 : 1+compressionMethodsLen]

// A ClientHello may be following by trailing data: RFC 4346 section 7.4.1.2
return true;
return true
}

type serverHelloMsg struct {
raw []byte;
major, minor uint8;
random []byte;
sessionId []byte;
cipherSuite uint16;
compressionMethod uint8;
raw []byte
major, minor uint8
random []byte
sessionId []byte
cipherSuite uint16
compressionMethod uint8
}

func (m *serverHelloMsg) marshal() []byte {
@@ -100,53 +100,53 @@ func (m *serverHelloMsg) marshal() []byte {
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;
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]);
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:];
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];
m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
m.compressionMethod = data[2]

// Trailing data is allowed because extensions may be present.
return true;
return true
}

type certificateMsg struct {
raw []byte;
certificates [][]byte;
raw []byte
certificates [][]byte
}

func (m *certificateMsg) marshal() (x []byte) {
@@ -154,34 +154,34 @@ func (m *certificateMsg) marshal() (x []byte) {
return m.raw
}

var i int;
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);
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);
certificateOctets := length - 3
x[4] = uint8(certificateOctets >> 16)
x[5] = uint8(certificateOctets >> 8)
x[6] = uint8(certificateOctets)

y := x[7:];
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):];
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;
m.raw = x
return
}

func (m *certificateMsg) unmarshal(data []byte) bool {
@@ -189,44 +189,44 @@ func (m *certificateMsg) unmarshal(data []byte) bool {
return false
}

m.raw = data;
certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6]);
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:];
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]);
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++;
d = d[3+certLen:]
certsLen -= 3 + certLen
numCerts++
}

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

type serverHelloDoneMsg struct{}

func (m *serverHelloDoneMsg) marshal() []byte {
x := make([]byte, 4);
x[0] = typeServerHelloDone;
return x;
x := make([]byte, 4)
x[0] = typeServerHelloDone
return x
}

func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
@@ -234,44 +234,44 @@ func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
}

type clientKeyExchangeMsg struct {
raw []byte;
ciphertext []byte;
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;
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;
m.raw = data
if len(data) < 7 {
return false
}
cipherTextLen := int(data[4])<<8 | int(data[5]);
cipherTextLen := int(data[4])<<8 | int(data[5])
if len(data) != 6+cipherTextLen {
return false
}
m.ciphertext = data[6:];
return true;
m.ciphertext = data[6:]
return true
}

type finishedMsg struct {
raw []byte;
verifyData []byte;
raw []byte
verifyData []byte
}

func (m *finishedMsg) marshal() (x []byte) {
@@ -279,19 +279,19 @@ func (m *finishedMsg) marshal() (x []byte) {
return m.raw
}

x = make([]byte, 16);
x[0] = typeFinished;
x[3] = 12;
copy(x[4:], m.verifyData);
m.raw = x;
return;
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;
m.raw = data
if len(data) != 4+12 {
return false
}
m.verifyData = data[4:];
return true;
m.verifyData = data[4:]
return true
}

+ 54
- 54
handshake_messages_test.go ファイルの表示

@@ -5,10 +5,10 @@
package tls

import (
"rand";
"reflect";
"testing";
"testing/quick";
"rand"
"reflect"
"testing"
"testing/quick"
)

var tests = []interface{}{
@@ -20,41 +20,41 @@ var tests = []interface{}{
}

type testMessage interface {
marshal() []byte;
unmarshal([]byte) bool;
marshal() []byte
unmarshal([]byte) bool
}

func TestMarshalUnmarshal(t *testing.T) {
rand := rand.New(rand.NewSource(0));
rand := rand.New(rand.NewSource(0))
for i, iface := range tests {
ty := reflect.NewValue(iface).Type();
ty := reflect.NewValue(iface).Type()

for j := 0; j < 100; j++ {
v, ok := quick.Value(ty, rand);
v, ok := quick.Value(ty, rand)
if !ok {
t.Errorf("#%d: failed to create value", i);
break;
t.Errorf("#%d: failed to create value", i)
break
}

m1 := v.Interface().(testMessage);
marshaled := m1.marshal();
m2 := iface.(testMessage);
m1 := v.Interface().(testMessage)
marshaled := m1.marshal()
m2 := iface.(testMessage)
if !m2.unmarshal(marshaled) {
t.Errorf("#%d failed to unmarshal %#v", i, m1);
break;
t.Errorf("#%d failed to unmarshal %#v", i, m1)
break
}
m2.marshal(); // to fill any marshal cache in the message
m2.marshal() // to fill any marshal cache in the message

if !reflect.DeepEqual(m1, m2) {
t.Errorf("#%d got:%#v want:%#v", i, m1, m2);
break;
t.Errorf("#%d got:%#v want:%#v", i, m1, m2)
break
}

// Now check that all prefixes are invalid.
for j := 0; j < len(marshaled); j++ {
if m2.unmarshal(marshaled[0:j]) {
t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1);
break;
t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1)
break
}
}
}
@@ -62,71 +62,71 @@ func TestMarshalUnmarshal(t *testing.T) {
}

func TestFuzz(t *testing.T) {
rand := rand.New(rand.NewSource(0));
rand := rand.New(rand.NewSource(0))
for _, iface := range tests {
m := iface.(testMessage);
m := iface.(testMessage)

for j := 0; j < 1000; j++ {
len := rand.Intn(100);
bytes := randomBytes(len, rand);
len := rand.Intn(100)
bytes := randomBytes(len, rand)
// This just looks for crashes due to bounds errors etc.
m.unmarshal(bytes);
m.unmarshal(bytes)
}
}
}

func randomBytes(n int, rand *rand.Rand) []byte {
r := make([]byte, n);
r := make([]byte, n)
for i := 0; i < n; i++ {
r[i] = byte(rand.Int31())
}
return r;
return r
}

func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &clientHelloMsg{};
m.major = uint8(rand.Intn(256));
m.minor = uint8(rand.Intn(256));
m.random = randomBytes(32, rand);
m.sessionId = randomBytes(rand.Intn(32), rand);
m.cipherSuites = make([]uint16, rand.Intn(63)+1);
m := &clientHelloMsg{}
m.major = uint8(rand.Intn(256))
m.minor = uint8(rand.Intn(256))
m.random = randomBytes(32, rand)
m.sessionId = randomBytes(rand.Intn(32), rand)
m.cipherSuites = make([]uint16, rand.Intn(63)+1)
for i := 0; i < len(m.cipherSuites); i++ {
m.cipherSuites[i] = uint16(rand.Int31())
}
m.compressionMethods = randomBytes(rand.Intn(63)+1, rand);
m.compressionMethods = randomBytes(rand.Intn(63)+1, rand)

return reflect.NewValue(m);
return reflect.NewValue(m)
}

func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &serverHelloMsg{};
m.major = uint8(rand.Intn(256));
m.minor = uint8(rand.Intn(256));
m.random = randomBytes(32, rand);
m.sessionId = randomBytes(rand.Intn(32), rand);
m.cipherSuite = uint16(rand.Int31());
m.compressionMethod = uint8(rand.Intn(256));
return reflect.NewValue(m);
m := &serverHelloMsg{}
m.major = uint8(rand.Intn(256))
m.minor = uint8(rand.Intn(256))
m.random = randomBytes(32, rand)
m.sessionId = randomBytes(rand.Intn(32), rand)
m.cipherSuite = uint16(rand.Int31())
m.compressionMethod = uint8(rand.Intn(256))
return reflect.NewValue(m)
}

func (*certificateMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &certificateMsg{};
numCerts := rand.Intn(20);
m.certificates = make([][]byte, numCerts);
m := &certificateMsg{}
numCerts := rand.Intn(20)
m.certificates = make([][]byte, numCerts)
for i := 0; i < numCerts; i++ {
m.certificates[i] = randomBytes(rand.Intn(10)+1, rand)
}
return reflect.NewValue(m);
return reflect.NewValue(m)
}

func (*clientKeyExchangeMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &clientKeyExchangeMsg{};
m.ciphertext = randomBytes(rand.Intn(1000)+1, rand);
return reflect.NewValue(m);
m := &clientKeyExchangeMsg{}
m.ciphertext = randomBytes(rand.Intn(1000)+1, rand)
return reflect.NewValue(m)
}

func (*finishedMsg) Generate(rand *rand.Rand, size int) reflect.Value {
m := &finishedMsg{};
m.verifyData = randomBytes(12, rand);
return reflect.NewValue(m);
m := &finishedMsg{}
m.verifyData = randomBytes(12, rand)
return reflect.NewValue(m)
}

+ 108
- 108
handshake_server.go ファイルの表示

@@ -13,17 +13,17 @@ package tls
// channel in the message (ChangeCipherSpec).

import (
"crypto/hmac";
"crypto/rc4";
"crypto/rsa";
"crypto/sha1";
"crypto/subtle";
"io";
"crypto/hmac"
"crypto/rc4"
"crypto/rsa"
"crypto/sha1"
"crypto/subtle"
"io"
)

type cipherSuite struct {
id uint16; // The number of this suite on the wire.
hashLength, cipherKeyLength int;
id uint16 // The number of this suite on the wire.
hashLength, cipherKeyLength int
// TODO(agl): need a method to create the cipher and hash interfaces.
}

@@ -33,118 +33,118 @@ var cipherSuites = []cipherSuite{

// A serverHandshake performs the server side of the TLS 1.1 handshake protocol.
type serverHandshake struct {
writeChan chan<- interface{};
controlChan chan<- interface{};
msgChan <-chan interface{};
config *Config;
writeChan chan<- interface{}
controlChan chan<- interface{}
msgChan <-chan interface{}
config *Config
}

func (h *serverHandshake) loop(writeChan chan<- interface{}, controlChan chan<- interface{}, msgChan <-chan interface{}, config *Config) {
h.writeChan = writeChan;
h.controlChan = controlChan;
h.msgChan = msgChan;
h.config = config;
h.writeChan = writeChan
h.controlChan = controlChan
h.msgChan = msgChan
h.config = config

defer close(writeChan);
defer close(controlChan);
defer close(writeChan)
defer close(controlChan)

clientHello, ok := h.readHandshakeMsg().(*clientHelloMsg);
clientHello, ok := h.readHandshakeMsg().(*clientHelloMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
major, minor, ok := mutualVersion(clientHello.major, clientHello.minor);
major, minor, ok := mutualVersion(clientHello.major, clientHello.minor)
if !ok {
h.error(alertProtocolVersion);
return;
h.error(alertProtocolVersion)
return
}

finishedHash := newFinishedHash();
finishedHash.Write(clientHello.marshal());
finishedHash := newFinishedHash()
finishedHash.Write(clientHello.marshal())

hello := new(serverHelloMsg);
hello := new(serverHelloMsg)

// We only support a single ciphersuite so we look for it in the list
// of client supported suites.
//
// TODO(agl): Add additional cipher suites.
var suite *cipherSuite;
var suite *cipherSuite

for _, id := range clientHello.cipherSuites {
for _, supported := range cipherSuites {
if supported.id == id {
suite = &supported;
break;
suite = &supported
break
}
}
}

foundCompression := false;
foundCompression := false
// We only support null compression, so check that the client offered it.
for _, compression := range clientHello.compressionMethods {
if compression == compressionNone {
foundCompression = true;
break;
foundCompression = true
break
}
}

if suite == nil || !foundCompression {
h.error(alertHandshakeFailure);
return;
}
hello.major = major;
hello.minor = minor;
hello.cipherSuite = suite.id;
currentTime := uint32(config.Time());
hello.random = make([]byte, 32);
hello.random[0] = byte(currentTime >> 24);
hello.random[1] = byte(currentTime >> 16);
hello.random[2] = byte(currentTime >> 8);
hello.random[3] = byte(currentTime);
_, err := io.ReadFull(config.Rand, hello.random[4:]);
h.error(alertHandshakeFailure)
return
}
hello.major = major
hello.minor = minor
hello.cipherSuite = suite.id
currentTime := uint32(config.Time())
hello.random = make([]byte, 32)
hello.random[0] = byte(currentTime >> 24)
hello.random[1] = byte(currentTime >> 16)
hello.random[2] = byte(currentTime >> 8)
hello.random[3] = byte(currentTime)
_, err := io.ReadFull(config.Rand, hello.random[4:])
if err != nil {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}
hello.compressionMethod = compressionNone;
hello.compressionMethod = compressionNone

finishedHash.Write(hello.marshal());
writeChan <- writerSetVersion{major, minor};
writeChan <- hello;
finishedHash.Write(hello.marshal())
writeChan <- writerSetVersion{major, minor}
writeChan <- hello

if len(config.Certificates) == 0 {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}

certMsg := new(certificateMsg);
certMsg.certificates = config.Certificates[0].Certificate;
finishedHash.Write(certMsg.marshal());
writeChan <- certMsg;
certMsg := new(certificateMsg)
certMsg.certificates = config.Certificates[0].Certificate
finishedHash.Write(certMsg.marshal())
writeChan <- certMsg

helloDone := new(serverHelloDoneMsg);
finishedHash.Write(helloDone.marshal());
writeChan <- helloDone;
helloDone := new(serverHelloDoneMsg)
finishedHash.Write(helloDone.marshal())
writeChan <- helloDone

ckx, ok := h.readHandshakeMsg().(*clientKeyExchangeMsg);
ckx, ok := h.readHandshakeMsg().(*clientKeyExchangeMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
finishedHash.Write(ckx.marshal());
finishedHash.Write(ckx.marshal())

preMasterSecret := make([]byte, 48);
_, err = io.ReadFull(config.Rand, preMasterSecret[2:]);
preMasterSecret := make([]byte, 48)
_, err = io.ReadFull(config.Rand, preMasterSecret[2:])
if err != nil {
h.error(alertInternalError);
return;
h.error(alertInternalError)
return
}

err = rsa.DecryptPKCS1v15SessionKey(config.Rand, config.Certificates[0].PrivateKey, ckx.ciphertext, preMasterSecret);
err = rsa.DecryptPKCS1v15SessionKey(config.Rand, config.Certificates[0].PrivateKey, ckx.ciphertext, preMasterSecret)
if err != nil {
h.error(alertHandshakeFailure);
return;
h.error(alertHandshakeFailure)
return
}
// We don't check the version number in the premaster secret. For one,
// by checking it, we would leak information about the validity of the
@@ -154,70 +154,70 @@ func (h *serverHandshake) loop(writeChan chan<- interface{}, controlChan chan<-
// 7.4.7.1 of RFC 4346.

masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength);
keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)

_, ok = h.readHandshakeMsg().(changeCipherSpec);
_, ok = h.readHandshakeMsg().(changeCipherSpec)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}

cipher, _ := rc4.NewCipher(clientKey);
controlChan <- &newCipherSpec{cipher, hmac.New(sha1.New(), clientMAC)};
cipher, _ := rc4.NewCipher(clientKey)
controlChan <- &newCipherSpec{cipher, hmac.New(sha1.New(), clientMAC)}

clientFinished, ok := h.readHandshakeMsg().(*finishedMsg);
clientFinished, ok := h.readHandshakeMsg().(*finishedMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}

verify := finishedHash.clientSum(masterSecret);
verify := finishedHash.clientSum(masterSecret)
if len(verify) != len(clientFinished.verifyData) ||
subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
h.error(alertHandshakeFailure);
return;
h.error(alertHandshakeFailure)
return
}

controlChan <- ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0};
controlChan <- ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0}

finishedHash.Write(clientFinished.marshal());
finishedHash.Write(clientFinished.marshal())

cipher2, _ := rc4.NewCipher(serverKey);
writeChan <- writerChangeCipherSpec{cipher2, hmac.New(sha1.New(), serverMAC)};
cipher2, _ := rc4.NewCipher(serverKey)
writeChan <- writerChangeCipherSpec{cipher2, hmac.New(sha1.New(), serverMAC)}

finished := new(finishedMsg);
finished.verifyData = finishedHash.serverSum(masterSecret);
writeChan <- finished;
finished := new(finishedMsg)
finished.verifyData = finishedHash.serverSum(masterSecret)
writeChan <- finished

writeChan <- writerEnableApplicationData{};
writeChan <- writerEnableApplicationData{}

for {
_, ok := h.readHandshakeMsg().(*clientHelloMsg);
_, ok := h.readHandshakeMsg().(*clientHelloMsg)
if !ok {
h.error(alertUnexpectedMessage);
return;
h.error(alertUnexpectedMessage)
return
}
// We reject all renegotication requests.
writeChan <- alert{alertLevelWarning, alertNoRenegotiation};
writeChan <- alert{alertLevelWarning, alertNoRenegotiation}
}
}

func (h *serverHandshake) readHandshakeMsg() interface{} {
v := <-h.msgChan;
v := <-h.msgChan
if closed(h.msgChan) {
// If the channel closed then the processor received an error
// from the peer and we don't want to echo it back to them.
h.msgChan = nil;
return 0;
h.msgChan = nil
return 0
}
if _, ok := v.(alert); ok {
// We got an alert from the processor. We forward to the writer
// and shutdown.
h.writeChan <- v;
h.msgChan = nil;
return 0;
h.writeChan <- v
h.msgChan = nil
return 0
}
return v;
return v
}

func (h *serverHandshake) error(e alertType) {
@@ -227,9 +227,9 @@ func (h *serverHandshake) error(e alertType) {
go func() {
for _ = range h.msgChan {
}
}();
h.controlChan <- ConnectionState{false, "", e};
close(h.controlChan);
h.writeChan <- alert{alertLevelError, e};
}()
h.controlChan <- ConnectionState{false, "", e}
close(h.controlChan)
h.writeChan <- alert{alertLevelError, e}
}
}

+ 81
- 81
handshake_server_test.go ファイルの表示

@@ -5,12 +5,12 @@
package tls

import (
"bytes";
"big";
"crypto/rsa";
"os";
"testing";
"testing/script";
"bytes"
"big"
"crypto/rsa"
"os"
"testing"
"testing/script"
)

type zeroSource struct{}
@@ -20,41 +20,41 @@ func (zeroSource) Read(b []byte) (n int, err os.Error) {
b[i] = 0
}

return len(b), nil;
return len(b), nil
}

var testConfig *Config

func init() {
testConfig = new(Config);
testConfig.Time = func() int64 { return 0 };
testConfig.Rand = zeroSource{};
testConfig.Certificates = make([]Certificate, 1);
testConfig.Certificates[0].Certificate = [][]byte{testCertificate};
testConfig.Certificates[0].PrivateKey = testPrivateKey;
testConfig = new(Config)
testConfig.Time = func() int64 { return 0 }
testConfig.Rand = zeroSource{}
testConfig.Certificates = make([]Certificate, 1)
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
testConfig.Certificates[0].PrivateKey = testPrivateKey
}

func setupServerHandshake() (writeChan chan interface{}, controlChan chan interface{}, msgChan chan interface{}) {
sh := new(serverHandshake);
writeChan = make(chan interface{});
controlChan = make(chan interface{});
msgChan = make(chan interface{});
sh := new(serverHandshake)
writeChan = make(chan interface{})
controlChan = make(chan interface{})
msgChan = make(chan interface{})

go sh.loop(writeChan, controlChan, msgChan, testConfig);
return;
go sh.loop(writeChan, controlChan, msgChan, testConfig)
return
}

func testClientHelloFailure(t *testing.T, clientHello interface{}, expectedAlert alertType) {
writeChan, controlChan, msgChan := setupServerHandshake();
defer close(msgChan);
writeChan, controlChan, msgChan := setupServerHandshake()
defer close(msgChan)

send := script.NewEvent("send", nil, script.Send{msgChan, clientHello});
recvAlert := script.NewEvent("recv alert", []*script.Event{send}, script.Recv{writeChan, alert{alertLevelError, expectedAlert}});
close1 := script.NewEvent("msgChan close", []*script.Event{recvAlert}, script.Closed{writeChan});
recvState := script.NewEvent("recv state", []*script.Event{send}, script.Recv{controlChan, ConnectionState{false, "", expectedAlert}});
close2 := script.NewEvent("controlChan close", []*script.Event{recvState}, script.Closed{controlChan});
send := script.NewEvent("send", nil, script.Send{msgChan, clientHello})
recvAlert := script.NewEvent("recv alert", []*script.Event{send}, script.Recv{writeChan, alert{alertLevelError, expectedAlert}})
close1 := script.NewEvent("msgChan close", []*script.Event{recvAlert}, script.Closed{writeChan})
recvState := script.NewEvent("recv state", []*script.Event{send}, script.Recv{controlChan, ConnectionState{false, "", expectedAlert}})
close2 := script.NewEvent("controlChan close", []*script.Event{recvState}, script.Closed{controlChan})

err := script.Perform(0, []*script.Event{send, recvAlert, close1, recvState, close2});
err := script.Perform(0, []*script.Event{send, recvAlert, close1, recvState, close2})
if err != nil {
t.Errorf("Got error: %s", err)
}
@@ -67,125 +67,125 @@ func TestSimpleError(t *testing.T) {
var badProtocolVersions = []uint8{0, 0, 0, 5, 1, 0, 1, 5, 2, 0, 2, 5, 3, 0}

func TestRejectBadProtocolVersion(t *testing.T) {
clientHello := new(clientHelloMsg);
clientHello := new(clientHelloMsg)

for i := 0; i < len(badProtocolVersions); i += 2 {
clientHello.major = badProtocolVersions[i];
clientHello.minor = badProtocolVersions[i+1];
clientHello.major = badProtocolVersions[i]
clientHello.minor = badProtocolVersions[i+1]

testClientHelloFailure(t, clientHello, alertProtocolVersion);
testClientHelloFailure(t, clientHello, alertProtocolVersion)
}
}

func TestNoSuiteOverlap(t *testing.T) {
clientHello := &clientHelloMsg{nil, 3, 1, nil, nil, []uint16{0xff00}, []uint8{0}};
testClientHelloFailure(t, clientHello, alertHandshakeFailure);
clientHello := &clientHelloMsg{nil, 3, 1, nil, nil, []uint16{0xff00}, []uint8{0}}
testClientHelloFailure(t, clientHello, alertHandshakeFailure)

}

func TestNoCompressionOverlap(t *testing.T) {
clientHello := &clientHelloMsg{nil, 3, 1, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}};
testClientHelloFailure(t, clientHello, alertHandshakeFailure);
clientHello := &clientHelloMsg{nil, 3, 1, nil, nil, []uint16{TLS_RSA_WITH_RC4_128_SHA}, []uint8{0xff}}
testClientHelloFailure(t, clientHello, alertHandshakeFailure)
}

func matchServerHello(v interface{}) bool {
serverHello, ok := v.(*serverHelloMsg);
serverHello, ok := v.(*serverHelloMsg)
if !ok {
return false
}
return serverHello.major == 3 &&
serverHello.minor == 2 &&
serverHello.cipherSuite == TLS_RSA_WITH_RC4_128_SHA &&
serverHello.compressionMethod == compressionNone;
serverHello.compressionMethod == compressionNone
}

func TestAlertForwarding(t *testing.T) {
writeChan, controlChan, msgChan := setupServerHandshake();
defer close(msgChan);
writeChan, controlChan, msgChan := setupServerHandshake()
defer close(msgChan)

a := alert{alertLevelError, alertNoRenegotiation};
sendAlert := script.NewEvent("send alert", nil, script.Send{msgChan, a});
recvAlert := script.NewEvent("recv alert", []*script.Event{sendAlert}, script.Recv{writeChan, a});
closeWriter := script.NewEvent("close writer", []*script.Event{recvAlert}, script.Closed{writeChan});
closeControl := script.NewEvent("close control", []*script.Event{recvAlert}, script.Closed{controlChan});
a := alert{alertLevelError, alertNoRenegotiation}
sendAlert := script.NewEvent("send alert", nil, script.Send{msgChan, a})
recvAlert := script.NewEvent("recv alert", []*script.Event{sendAlert}, script.Recv{writeChan, a})
closeWriter := script.NewEvent("close writer", []*script.Event{recvAlert}, script.Closed{writeChan})
closeControl := script.NewEvent("close control", []*script.Event{recvAlert}, script.Closed{controlChan})

err := script.Perform(0, []*script.Event{sendAlert, recvAlert, closeWriter, closeControl});
err := script.Perform(0, []*script.Event{sendAlert, recvAlert, closeWriter, closeControl})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestClose(t *testing.T) {
writeChan, controlChan, msgChan := setupServerHandshake();
writeChan, controlChan, msgChan := setupServerHandshake()

close := script.NewEvent("close", nil, script.Close{msgChan});
closed1 := script.NewEvent("closed1", []*script.Event{close}, script.Closed{writeChan});
closed2 := script.NewEvent("closed2", []*script.Event{close}, script.Closed{controlChan});
close := script.NewEvent("close", nil, script.Close{msgChan})
closed1 := script.NewEvent("closed1", []*script.Event{close}, script.Closed{writeChan})
closed2 := script.NewEvent("closed2", []*script.Event{close}, script.Closed{controlChan})

err := script.Perform(0, []*script.Event{close, closed1, closed2});
err := script.Perform(0, []*script.Event{close, closed1, closed2})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func matchCertificate(v interface{}) bool {
cert, ok := v.(*certificateMsg);
cert, ok := v.(*certificateMsg)
if !ok {
return false
}
return len(cert.certificates) == 1 &&
bytes.Compare(cert.certificates[0], testCertificate) == 0;
bytes.Compare(cert.certificates[0], testCertificate) == 0
}

func matchSetCipher(v interface{}) bool {
_, ok := v.(writerChangeCipherSpec);
return ok;
_, ok := v.(writerChangeCipherSpec)
return ok
}

func matchDone(v interface{}) bool {
_, ok := v.(*serverHelloDoneMsg);
return ok;
_, ok := v.(*serverHelloDoneMsg)
return ok
}

func matchFinished(v interface{}) bool {
finished, ok := v.(*finishedMsg);
finished, ok := v.(*finishedMsg)
if !ok {
return false
}
return bytes.Compare(finished.verifyData, fromHex("29122ae11453e631487b02ed")) == 0;
return bytes.Compare(finished.verifyData, fromHex("29122ae11453e631487b02ed")) == 0
}

func matchNewCipherSpec(v interface{}) bool {
_, ok := v.(*newCipherSpec);
return ok;
_, ok := v.(*newCipherSpec)
return ok
}

func TestFullHandshake(t *testing.T) {
writeChan, controlChan, msgChan := setupServerHandshake();
defer close(msgChan);
writeChan, controlChan, msgChan := setupServerHandshake()
defer close(msgChan)

// The values for this test were obtained from running `gnutls-cli --insecure --debug 9`
clientHello := &clientHelloMsg{fromHex("0100007603024aef7d77e4686d5dfd9d953dfe280788759ffd440867d687670216da45516b310000340033004500390088001600320044003800870013006600900091008f008e002f004100350084000a00050004008c008d008b008a01000019000900030200010000000e000c0000093132372e302e302e31"), 3, 2, fromHex("4aef7d77e4686d5dfd9d953dfe280788759ffd440867d687670216da45516b31"), nil, []uint16{0x33, 0x45, 0x39, 0x88, 0x16, 0x32, 0x44, 0x38, 0x87, 0x13, 0x66, 0x90, 0x91, 0x8f, 0x8e, 0x2f, 0x41, 0x35, 0x84, 0xa, 0x5, 0x4, 0x8c, 0x8d, 0x8b, 0x8a}, []uint8{0x0}};
clientHello := &clientHelloMsg{fromHex("0100007603024aef7d77e4686d5dfd9d953dfe280788759ffd440867d687670216da45516b310000340033004500390088001600320044003800870013006600900091008f008e002f004100350084000a00050004008c008d008b008a01000019000900030200010000000e000c0000093132372e302e302e31"), 3, 2, fromHex("4aef7d77e4686d5dfd9d953dfe280788759ffd440867d687670216da45516b31"), nil, []uint16{0x33, 0x45, 0x39, 0x88, 0x16, 0x32, 0x44, 0x38, 0x87, 0x13, 0x66, 0x90, 0x91, 0x8f, 0x8e, 0x2f, 0x41, 0x35, 0x84, 0xa, 0x5, 0x4, 0x8c, 0x8d, 0x8b, 0x8a}, []uint8{0x0}}

sendHello := script.NewEvent("send hello", nil, script.Send{msgChan, clientHello});
setVersion := script.NewEvent("set version", []*script.Event{sendHello}, script.Recv{writeChan, writerSetVersion{3, 2}});
recvHello := script.NewEvent("recv hello", []*script.Event{setVersion}, script.RecvMatch{writeChan, matchServerHello});
recvCert := script.NewEvent("recv cert", []*script.Event{recvHello}, script.RecvMatch{writeChan, matchCertificate});
recvDone := script.NewEvent("recv done", []*script.Event{recvCert}, script.RecvMatch{writeChan, matchDone});
sendHello := script.NewEvent("send hello", nil, script.Send{msgChan, clientHello})
setVersion := script.NewEvent("set version", []*script.Event{sendHello}, script.Recv{writeChan, writerSetVersion{3, 2}})
recvHello := script.NewEvent("recv hello", []*script.Event{setVersion}, script.RecvMatch{writeChan, matchServerHello})
recvCert := script.NewEvent("recv cert", []*script.Event{recvHello}, script.RecvMatch{writeChan, matchCertificate})
recvDone := script.NewEvent("recv done", []*script.Event{recvCert}, script.RecvMatch{writeChan, matchDone})

ckx := &clientKeyExchangeMsg{nil, fromHex("872e1fee5f37dd86f3215938ac8de20b302b90074e9fb93097e6b7d1286d0f45abf2daf179deb618bb3c70ed0afee6ee24476ee4649e5a23358143c0f1d9c251")};
sendCKX := script.NewEvent("send ckx", []*script.Event{recvDone}, script.Send{msgChan, ckx});
ckx := &clientKeyExchangeMsg{nil, fromHex("872e1fee5f37dd86f3215938ac8de20b302b90074e9fb93097e6b7d1286d0f45abf2daf179deb618bb3c70ed0afee6ee24476ee4649e5a23358143c0f1d9c251")}
sendCKX := script.NewEvent("send ckx", []*script.Event{recvDone}, script.Send{msgChan, ckx})

sendCCS := script.NewEvent("send ccs", []*script.Event{sendCKX}, script.Send{msgChan, changeCipherSpec{}});
recvNCS := script.NewEvent("recv done", []*script.Event{sendCCS}, script.RecvMatch{controlChan, matchNewCipherSpec});
sendCCS := script.NewEvent("send ccs", []*script.Event{sendCKX}, script.Send{msgChan, changeCipherSpec{}})
recvNCS := script.NewEvent("recv done", []*script.Event{sendCCS}, script.RecvMatch{controlChan, matchNewCipherSpec})

finished := &finishedMsg{nil, fromHex("c8faca5d242f4423325c5b1a")};
sendFinished := script.NewEvent("send finished", []*script.Event{recvNCS}, script.Send{msgChan, finished});
recvFinished := script.NewEvent("recv finished", []*script.Event{sendFinished}, script.RecvMatch{writeChan, matchFinished});
setCipher := script.NewEvent("set cipher", []*script.Event{sendFinished}, script.RecvMatch{writeChan, matchSetCipher});
recvConnectionState := script.NewEvent("recv state", []*script.Event{sendFinished}, script.Recv{controlChan, ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0}});
finished := &finishedMsg{nil, fromHex("c8faca5d242f4423325c5b1a")}
sendFinished := script.NewEvent("send finished", []*script.Event{recvNCS}, script.Send{msgChan, finished})
recvFinished := script.NewEvent("recv finished", []*script.Event{sendFinished}, script.RecvMatch{writeChan, matchFinished})
setCipher := script.NewEvent("set cipher", []*script.Event{sendFinished}, script.RecvMatch{writeChan, matchSetCipher})
recvConnectionState := script.NewEvent("recv state", []*script.Event{sendFinished}, script.Recv{controlChan, ConnectionState{true, "TLS_RSA_WITH_RC4_128_SHA", 0}})

err := script.Perform(0, []*script.Event{sendHello, setVersion, recvHello, recvCert, recvDone, sendCKX, sendCCS, recvNCS, sendFinished, setCipher, recvConnectionState, recvFinished});
err := script.Perform(0, []*script.Event{sendHello, setVersion, recvHello, recvCert, recvDone, sendCKX, sendCCS, recvNCS, sendFinished, setCipher, recvConnectionState, recvFinished})
if err != nil {
t.Errorf("Got error: %s", err)
}
@@ -194,9 +194,9 @@ func TestFullHandshake(t *testing.T) {
var testCertificate = fromHex("3082025930820203a003020102020900c2ec326b95228959300d06092a864886f70d01010505003054310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464310d300b0603550403130474657374301e170d3039313032303232323434355a170d3130313032303232323434355a3054310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464310d300b0603550403130474657374305c300d06092a864886f70d0101010500034b003048024100b2990f49c47dfa8cd400ae6a4d1b8a3b6a13642b23f28b003bfb97790ade9a4cc82b8b2a81747ddec08b6296e53a08c331687ef25c4bf4936ba1c0e6041e9d150203010001a381b73081b4301d0603551d0e0416041478a06086837c9293a8c9b70c0bdabdb9d77eeedf3081840603551d23047d307b801478a06086837c9293a8c9b70c0bdabdb9d77eeedfa158a4563054310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464310d300b0603550403130474657374820900c2ec326b95228959300c0603551d13040530030101ff300d06092a864886f70d0101050500034100ac23761ae1349d85a439caad4d0b932b09ea96de1917c3e0507c446f4838cb3076fb4d431db8c1987e96f1d7a8a2054dea3a64ec99a3f0eda4d47a163bf1f6ac")

func bigFromString(s string) *big.Int {
ret := new(big.Int);
ret.SetString(s, 10);
return ret;
ret := new(big.Int)
ret.SetString(s, 10)
return ret
}

var testPrivateKey = &rsa.PrivateKey{


+ 73
- 73
prf.go ファイルの表示

@@ -5,59 +5,59 @@
package tls

import (
"crypto/hmac";
"crypto/md5";
"crypto/sha1";
"hash";
"os";
"strings";
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"hash"
"os"
"strings"
)

// Split a premaster secret in two as specified in RFC 4346, section 5.
func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
s1 = secret[0 : (len(secret)+1)/2];
s2 = secret[len(secret)/2:];
return;
s1 = secret[0 : (len(secret)+1)/2]
s2 = secret[len(secret)/2:]
return
}

// pHash implements the P_hash function, as defined in RFC 4346, section 5.
func pHash(result, secret, seed []byte, hash hash.Hash) {
h := hmac.New(hash, secret);
h.Write(seed);
a := h.Sum();
h := hmac.New(hash, secret)
h.Write(seed)
a := h.Sum()

j := 0;
j := 0
for j < len(result) {
h.Reset();
h.Write(a);
h.Write(seed);
b := h.Sum();
todo := len(b);
h.Reset()
h.Write(a)
h.Write(seed)
b := h.Sum()
todo := len(b)
if j+todo > len(result) {
todo = len(result) - j
}
copy(result[j:j+todo], b);
j += todo;
copy(result[j:j+todo], b)
j += todo

h.Reset();
h.Write(a);
a = h.Sum();
h.Reset()
h.Write(a)
a = h.Sum()
}
}

// pRF11 implements the TLS 1.1 pseudo-random function, as defined in RFC 4346, section 5.
func pRF11(result, secret, label, seed []byte) {
hashSHA1 := sha1.New();
hashMD5 := md5.New();
hashSHA1 := sha1.New()
hashMD5 := md5.New()

labelAndSeed := make([]byte, len(label)+len(seed));
copy(labelAndSeed, label);
copy(labelAndSeed[len(label):], seed);
labelAndSeed := make([]byte, len(label)+len(seed))
copy(labelAndSeed, label)
copy(labelAndSeed[len(label):], seed)

s1, s2 := splitPreMasterSecret(secret);
pHash(result, s1, labelAndSeed, hashMD5);
result2 := make([]byte, len(result));
pHash(result2, s2, labelAndSeed, hashSHA1);
s1, s2 := splitPreMasterSecret(secret)
pHash(result, s1, labelAndSeed, hashMD5)
result2 := make([]byte, len(result))
pHash(result2, s2, labelAndSeed, hashSHA1)

for i, b := range result2 {
result[i] ^= b
@@ -65,9 +65,9 @@ func pRF11(result, secret, label, seed []byte) {
}

const (
tlsRandomLength = 32; // Length of a random nonce in TLS 1.1.
masterSecretLength = 48; // Length of a master secret in TLS 1.1.
finishedVerifyLength = 12; // Length of verify_data in a Finished message.
tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
masterSecretLength = 48 // Length of a master secret in TLS 1.1.
finishedVerifyLength = 12 // Length of verify_data in a Finished message.
)

var masterSecretLabel = strings.Bytes("master secret")
@@ -79,32 +79,32 @@ var serverFinishedLabel = strings.Bytes("server finished")
// secret, given the lengths of the MAC and cipher keys, as defined in RFC
// 4346, section 6.3.
func keysFromPreMasterSecret11(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey []byte) {
var seed [tlsRandomLength * 2]byte;
copy(seed[0:len(clientRandom)], clientRandom);
copy(seed[len(clientRandom):], serverRandom);
masterSecret = make([]byte, masterSecretLength);
pRF11(masterSecret, preMasterSecret, masterSecretLabel, seed[0:]);
copy(seed[0:len(clientRandom)], serverRandom);
copy(seed[len(serverRandom):], clientRandom);
n := 2*macLen + 2*keyLen;
keyMaterial := make([]byte, n);
pRF11(keyMaterial, masterSecret, keyExpansionLabel, seed[0:]);
clientMAC = keyMaterial[0:macLen];
serverMAC = keyMaterial[macLen : macLen*2];
clientKey = keyMaterial[macLen*2 : macLen*2+keyLen];
serverKey = keyMaterial[macLen*2+keyLen:];
return;
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret = make([]byte, masterSecretLength)
pRF11(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
n := 2*macLen + 2*keyLen
keyMaterial := make([]byte, n)
pRF11(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
clientMAC = keyMaterial[0:macLen]
serverMAC = keyMaterial[macLen : macLen*2]
clientKey = keyMaterial[macLen*2 : macLen*2+keyLen]
serverKey = keyMaterial[macLen*2+keyLen:]
return
}

// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
clientMD5 hash.Hash;
clientSHA1 hash.Hash;
serverMD5 hash.Hash;
serverSHA1 hash.Hash;
clientMD5 hash.Hash
clientSHA1 hash.Hash
serverMD5 hash.Hash
serverSHA1 hash.Hash
}

func newFinishedHash() finishedHash {
@@ -112,36 +112,36 @@ func newFinishedHash() finishedHash {
}

func (h finishedHash) Write(msg []byte) (n int, err os.Error) {
h.clientMD5.Write(msg);
h.clientSHA1.Write(msg);
h.serverMD5.Write(msg);
h.serverSHA1.Write(msg);
return len(msg), nil;
h.clientMD5.Write(msg)
h.clientSHA1.Write(msg)
h.serverMD5.Write(msg)
h.serverSHA1.Write(msg)
return len(msg), nil
}

// finishedSum calculates the contents of the verify_data member of a Finished
// message given the MD5 and SHA1 hashes of a set of handshake messages.
func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
seed := make([]byte, len(md5)+len(sha1));
copy(seed, md5);
copy(seed[len(md5):], sha1);
out := make([]byte, finishedVerifyLength);
pRF11(out, masterSecret, label, seed);
return out;
seed := make([]byte, len(md5)+len(sha1))
copy(seed, md5)
copy(seed[len(md5):], sha1)
out := make([]byte, finishedVerifyLength)
pRF11(out, masterSecret, label, seed)
return out
}

// clientSum returns the contents of the verify_data member of a client's
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
md5 := h.clientMD5.Sum();
sha1 := h.clientSHA1.Sum();
return finishedSum(md5, sha1, clientFinishedLabel, masterSecret);
md5 := h.clientMD5.Sum()
sha1 := h.clientSHA1.Sum()
return finishedSum(md5, sha1, clientFinishedLabel, masterSecret)
}

// serverSum returns the contents of the verify_data member of a server's
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
md5 := h.serverMD5.Sum();
sha1 := h.serverSHA1.Sum();
return finishedSum(md5, sha1, serverFinishedLabel, masterSecret);
md5 := h.serverMD5.Sum()
sha1 := h.serverSHA1.Sum()
return finishedSum(md5, sha1, serverFinishedLabel, masterSecret)
}

+ 22
- 22
prf_test.go ファイルの表示

@@ -5,12 +5,12 @@
package tls

import (
"encoding/hex";
"testing";
"encoding/hex"
"testing"
)

type testSplitPreMasterSecretTest struct {
in, out1, out2 string;
in, out1, out2 string
}

var testSplitPreMasterSecretTests = []testSplitPreMasterSecretTest{
@@ -23,10 +23,10 @@ var testSplitPreMasterSecretTests = []testSplitPreMasterSecretTest{

func TestSplitPreMasterSecret(t *testing.T) {
for i, test := range testSplitPreMasterSecretTests {
in, _ := hex.DecodeString(test.in);
out1, out2 := splitPreMasterSecret(in);
s1 := hex.EncodeToString(out1);
s2 := hex.EncodeToString(out2);
in, _ := hex.DecodeString(test.in)
out1, out2 := splitPreMasterSecret(in)
s1 := hex.EncodeToString(out1)
s2 := hex.EncodeToString(out2)
if s1 != test.out1 || s2 != test.out2 {
t.Errorf("#%d: got: (%s, %s) want: (%s, %s)", i, s1, s2, test.out1, test.out2)
}
@@ -34,25 +34,25 @@ func TestSplitPreMasterSecret(t *testing.T) {
}

type testKeysFromTest struct {
preMasterSecret string;
clientRandom, serverRandom string;
masterSecret string;
clientMAC, serverMAC string;
clientKey, serverKey string;
macLen, keyLen int;
preMasterSecret string
clientRandom, serverRandom string
masterSecret string
clientMAC, serverMAC string
clientKey, serverKey string
macLen, keyLen int
}

func TestKeysFromPreMasterSecret(t *testing.T) {
for i, test := range testKeysFromTests {
in, _ := hex.DecodeString(test.preMasterSecret);
clientRandom, _ := hex.DecodeString(test.clientRandom);
serverRandom, _ := hex.DecodeString(test.serverRandom);
master, clientMAC, serverMAC, clientKey, serverKey := keysFromPreMasterSecret11(in, clientRandom, serverRandom, test.macLen, test.keyLen);
masterString := hex.EncodeToString(master);
clientMACString := hex.EncodeToString(clientMAC);
serverMACString := hex.EncodeToString(serverMAC);
clientKeyString := hex.EncodeToString(clientKey);
serverKeyString := hex.EncodeToString(serverKey);
in, _ := hex.DecodeString(test.preMasterSecret)
clientRandom, _ := hex.DecodeString(test.clientRandom)
serverRandom, _ := hex.DecodeString(test.serverRandom)
master, clientMAC, serverMAC, clientKey, serverKey := keysFromPreMasterSecret11(in, clientRandom, serverRandom, test.macLen, test.keyLen)
masterString := hex.EncodeToString(master)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
clientKeyString := hex.EncodeToString(clientKey)
serverKeyString := hex.EncodeToString(serverKey)
if masterString != test.masterSecret ||
clientMACString != test.clientMAC ||
serverMACString != test.serverMAC ||


+ 108
- 108
record_process.go ファイルの表示

@@ -10,27 +10,27 @@ package tls
// state, or for a notification when the state changes.

import (
"container/list";
"crypto/subtle";
"hash";
"container/list"
"crypto/subtle"
"hash"
)

// getConnectionState is a request from the application to get the current
// ConnectionState.
type getConnectionState struct {
reply chan<- ConnectionState;
reply chan<- ConnectionState
}

// waitConnectionState is a request from the application to be notified when
// the connection state changes.
type waitConnectionState struct {
reply chan<- ConnectionState;
reply chan<- ConnectionState
}

// connectionStateChange is a message from the handshake processor that the
// connection state has changed.
type connectionStateChange struct {
connState ConnectionState;
connState ConnectionState
}

// changeCipherSpec is a message send to the handshake processor to signal that
@@ -40,32 +40,32 @@ type changeCipherSpec struct{}
// newCipherSpec is a message from the handshake processor that future
// records should be processed with a new cipher and MAC function.
type newCipherSpec struct {
encrypt encryptor;
mac hash.Hash;
encrypt encryptor
mac hash.Hash
}

type recordProcessor struct {
decrypt encryptor;
mac hash.Hash;
seqNum uint64;
handshakeBuf []byte;
appDataChan chan<- []byte;
requestChan <-chan interface{};
controlChan <-chan interface{};
recordChan <-chan *record;
handshakeChan chan<- interface{};
decrypt encryptor
mac hash.Hash
seqNum uint64
handshakeBuf []byte
appDataChan chan<- []byte
requestChan <-chan interface{}
controlChan <-chan interface{}
recordChan <-chan *record
handshakeChan chan<- interface{}

// recordRead is nil when we don't wish to read any more.
recordRead <-chan *record;
recordRead <-chan *record
// appDataSend is nil when len(appData) == 0.
appDataSend chan<- []byte;
appDataSend chan<- []byte
// appData contains any application data queued for upstream.
appData []byte;
appData []byte
// A list of channels waiting for connState to change.
waitQueue *list.List;
connState ConnectionState;
shutdown bool;
header [13]byte;
waitQueue *list.List
connState ConnectionState
shutdown bool
header [13]byte
}

// drainRequestChannel processes messages from the request channel until it's closed.
@@ -84,24 +84,24 @@ func drainRequestChannel(requestChan <-chan interface{}, c ConnectionState) {
}

func (p *recordProcessor) loop(appDataChan chan<- []byte, requestChan <-chan interface{}, controlChan <-chan interface{}, recordChan <-chan *record, handshakeChan chan<- interface{}) {
noop := nop{};
p.decrypt = noop;
p.mac = noop;
p.waitQueue = list.New();
p.appDataChan = appDataChan;
p.requestChan = requestChan;
p.controlChan = controlChan;
p.recordChan = recordChan;
p.handshakeChan = handshakeChan;
p.recordRead = recordChan;
noop := nop{}
p.decrypt = noop
p.mac = noop
p.waitQueue = list.New()
p.appDataChan = appDataChan
p.requestChan = requestChan
p.controlChan = controlChan
p.recordChan = recordChan
p.handshakeChan = handshakeChan
p.recordRead = recordChan

for !p.shutdown {
select {
case p.appDataSend <- p.appData:
p.appData = nil;
p.appDataSend = nil;
p.recordRead = p.recordChan;
p.appData = nil
p.appDataSend = nil
p.recordRead = p.recordChan
case c := <-controlChan:
p.processControlMsg(c)
case r := <-requestChan:
@@ -111,24 +111,24 @@ func (p *recordProcessor) loop(appDataChan chan<- []byte, requestChan <-chan int
}
}

p.wakeWaiters();
go drainRequestChannel(p.requestChan, p.connState);
p.wakeWaiters()
go drainRequestChannel(p.requestChan, p.connState)
go func() {
for _ = range controlChan {
}
}();
}()

close(handshakeChan);
close(handshakeChan)
if len(p.appData) > 0 {
appDataChan <- p.appData
}
close(appDataChan);
close(appDataChan)
}

func (p *recordProcessor) processRequestMsg(requestMsg interface{}) {
if closed(p.requestChan) {
p.shutdown = true;
return;
p.shutdown = true
return
}

switch r := requestMsg.(type) {
@@ -138,51 +138,51 @@ func (p *recordProcessor) processRequestMsg(requestMsg interface{}) {
if p.connState.HandshakeComplete {
r.reply <- p.connState
}
p.waitQueue.PushBack(r.reply);
p.waitQueue.PushBack(r.reply)
}
}

func (p *recordProcessor) processControlMsg(msg interface{}) {
connState, ok := msg.(ConnectionState);
connState, ok := msg.(ConnectionState)
if !ok || closed(p.controlChan) {
p.shutdown = true;
return;
p.shutdown = true
return
}

p.connState = connState;
p.wakeWaiters();
p.connState = connState
p.wakeWaiters()
}

func (p *recordProcessor) wakeWaiters() {
for i := p.waitQueue.Front(); i != nil; i = i.Next() {
i.Value.(chan<- ConnectionState) <- p.connState
}
p.waitQueue.Init();
p.waitQueue.Init()
}

func (p *recordProcessor) processRecord(r *record) {
if closed(p.recordChan) {
p.shutdown = true;
return;
p.shutdown = true
return
}

p.decrypt.XORKeyStream(r.payload);
p.decrypt.XORKeyStream(r.payload)
if len(r.payload) < p.mac.Size() {
p.error(alertBadRecordMAC);
return;
p.error(alertBadRecordMAC)
return
}

fillMACHeader(&p.header, p.seqNum, len(r.payload)-p.mac.Size(), r);
p.seqNum++;
fillMACHeader(&p.header, p.seqNum, len(r.payload)-p.mac.Size(), r)
p.seqNum++

p.mac.Reset();
p.mac.Write(p.header[0:13]);
p.mac.Write(r.payload[0 : len(r.payload)-p.mac.Size()]);
macBytes := p.mac.Sum();
p.mac.Reset()
p.mac.Write(p.header[0:13])
p.mac.Write(r.payload[0 : len(r.payload)-p.mac.Size()])
macBytes := p.mac.Sum()

if subtle.ConstantTimeCompare(macBytes, r.payload[len(r.payload)-p.mac.Size():]) != 1 {
p.error(alertBadRecordMAC);
return;
p.error(alertBadRecordMAC)
return
}

switch r.contentType {
@@ -190,31 +190,31 @@ func (p *recordProcessor) processRecord(r *record) {
p.processHandshakeRecord(r.payload[0 : len(r.payload)-p.mac.Size()])
case recordTypeChangeCipherSpec:
if len(r.payload) != 1 || r.payload[0] != 1 {
p.error(alertUnexpectedMessage);
return;
p.error(alertUnexpectedMessage)
return
}

p.handshakeChan <- changeCipherSpec{};
newSpec, ok := (<-p.controlChan).(*newCipherSpec);
p.handshakeChan <- changeCipherSpec{}
newSpec, ok := (<-p.controlChan).(*newCipherSpec)
if !ok {
p.connState.Error = alertUnexpectedMessage;
p.shutdown = true;
return;
p.connState.Error = alertUnexpectedMessage
p.shutdown = true
return
}
p.decrypt = newSpec.encrypt;
p.mac = newSpec.mac;
p.seqNum = 0;
p.decrypt = newSpec.encrypt
p.mac = newSpec.mac
p.seqNum = 0
case recordTypeApplicationData:
if p.connState.HandshakeComplete == false {
p.error(alertUnexpectedMessage);
return;
p.error(alertUnexpectedMessage)
return
}
p.recordRead = nil;
p.appData = r.payload[0 : len(r.payload)-p.mac.Size()];
p.appDataSend = p.appDataChan;
p.recordRead = nil
p.appData = r.payload[0 : len(r.payload)-p.mac.Size()]
p.appDataSend = p.appDataChan
default:
p.error(alertUnexpectedMessage);
return;
p.error(alertUnexpectedMessage)
return
}
}

@@ -223,61 +223,61 @@ func (p *recordProcessor) processHandshakeRecord(data []byte) {
p.handshakeBuf = data
} else {
if len(p.handshakeBuf) > maxHandshakeMsg {
p.error(alertInternalError);
return;
p.error(alertInternalError)
return
}
newBuf := make([]byte, len(p.handshakeBuf)+len(data));
copy(newBuf, p.handshakeBuf);
copy(newBuf[len(p.handshakeBuf):], data);
p.handshakeBuf = newBuf;
newBuf := make([]byte, len(p.handshakeBuf)+len(data))
copy(newBuf, p.handshakeBuf)
copy(newBuf[len(p.handshakeBuf):], data)
p.handshakeBuf = newBuf
}

for len(p.handshakeBuf) >= 4 {
handshakeLen := int(p.handshakeBuf[1])<<16 |
int(p.handshakeBuf[2])<<8 |
int(p.handshakeBuf[3]);
int(p.handshakeBuf[3])
if handshakeLen+4 > len(p.handshakeBuf) {
break
}

bytes := p.handshakeBuf[0 : handshakeLen+4];
p.handshakeBuf = p.handshakeBuf[handshakeLen+4:];
bytes := p.handshakeBuf[0 : handshakeLen+4]
p.handshakeBuf = p.handshakeBuf[handshakeLen+4:]
if bytes[0] == typeFinished {
// Special case because Finished is synchronous: the
// handshake handler has to tell us if it's ok to start
// forwarding application data.
m := new(finishedMsg);
m := new(finishedMsg)
if !m.unmarshal(bytes) {
p.error(alertUnexpectedMessage)
}
p.handshakeChan <- m;
var ok bool;
p.connState, ok = (<-p.controlChan).(ConnectionState);
p.handshakeChan <- m
var ok bool
p.connState, ok = (<-p.controlChan).(ConnectionState)
if !ok || p.connState.Error != 0 {
p.shutdown = true;
return;
p.shutdown = true
return
}
} else {
msg, ok := parseHandshakeMsg(bytes);
msg, ok := parseHandshakeMsg(bytes)
if !ok {
p.error(alertUnexpectedMessage);
return;
p.error(alertUnexpectedMessage)
return
}
p.handshakeChan <- msg;
p.handshakeChan <- msg
}
}
}

func (p *recordProcessor) error(err alertType) {
close(p.handshakeChan);
p.connState.Error = err;
p.wakeWaiters();
p.shutdown = true;
close(p.handshakeChan)
p.connState.Error = err
p.wakeWaiters()
p.shutdown = true
}

func parseHandshakeMsg(data []byte) (interface{}, bool) {
var m interface {
unmarshal([]byte) bool;
unmarshal([]byte) bool
}

switch data[0] {
@@ -295,6 +295,6 @@ func parseHandshakeMsg(data []byte) (interface{}, bool) {
return nil, false
}

ok := m.unmarshal(data);
return m, ok;
ok := m.unmarshal(data)
return m, ok
}

+ 73
- 73
record_process_test.go ファイルの表示

@@ -5,132 +5,132 @@
package tls

import (
"encoding/hex";
"testing";
"testing/script";
"encoding/hex"
"testing"
"testing/script"
)

func setup() (appDataChan chan []byte, requestChan chan interface{}, controlChan chan interface{}, recordChan chan *record, handshakeChan chan interface{}) {
rp := new(recordProcessor);
appDataChan = make(chan []byte);
requestChan = make(chan interface{});
controlChan = make(chan interface{});
recordChan = make(chan *record);
handshakeChan = make(chan interface{});
go rp.loop(appDataChan, requestChan, controlChan, recordChan, handshakeChan);
return;
rp := new(recordProcessor)
appDataChan = make(chan []byte)
requestChan = make(chan interface{})
controlChan = make(chan interface{})
recordChan = make(chan *record)
handshakeChan = make(chan interface{})
go rp.loop(appDataChan, requestChan, controlChan, recordChan, handshakeChan)
return
}

func fromHex(s string) []byte {
b, _ := hex.DecodeString(s);
return b;
b, _ := hex.DecodeString(s)
return b
}

func TestNullConnectionState(t *testing.T) {
_, requestChan, controlChan, recordChan, _ := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
_, requestChan, controlChan, recordChan, _ := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)

// Test a simple request for the connection state.
replyChan := make(chan ConnectionState);
sendReq := script.NewEvent("send request", nil, script.Send{requestChan, getConnectionState{replyChan}});
getReply := script.NewEvent("get reply", []*script.Event{sendReq}, script.Recv{replyChan, ConnectionState{false, "", 0}});
replyChan := make(chan ConnectionState)
sendReq := script.NewEvent("send request", nil, script.Send{requestChan, getConnectionState{replyChan}})
getReply := script.NewEvent("get reply", []*script.Event{sendReq}, script.Recv{replyChan, ConnectionState{false, "", 0}})

err := script.Perform(0, []*script.Event{sendReq, getReply});
err := script.Perform(0, []*script.Event{sendReq, getReply})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestWaitConnectionState(t *testing.T) {
_, requestChan, controlChan, recordChan, _ := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
_, requestChan, controlChan, recordChan, _ := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)

// Test that waitConnectionState doesn't get a reply until the connection state changes.
replyChan := make(chan ConnectionState);
sendReq := script.NewEvent("send request", nil, script.Send{requestChan, waitConnectionState{replyChan}});
replyChan2 := make(chan ConnectionState);
sendReq2 := script.NewEvent("send request 2", []*script.Event{sendReq}, script.Send{requestChan, getConnectionState{replyChan2}});
getReply2 := script.NewEvent("get reply 2", []*script.Event{sendReq2}, script.Recv{replyChan2, ConnectionState{false, "", 0}});
sendState := script.NewEvent("send state", []*script.Event{getReply2}, script.Send{controlChan, ConnectionState{true, "test", 1}});
getReply := script.NewEvent("get reply", []*script.Event{sendState}, script.Recv{replyChan, ConnectionState{true, "test", 1}});
err := script.Perform(0, []*script.Event{sendReq, sendReq2, getReply2, sendState, getReply});
replyChan := make(chan ConnectionState)
sendReq := script.NewEvent("send request", nil, script.Send{requestChan, waitConnectionState{replyChan}})
replyChan2 := make(chan ConnectionState)
sendReq2 := script.NewEvent("send request 2", []*script.Event{sendReq}, script.Send{requestChan, getConnectionState{replyChan2}})
getReply2 := script.NewEvent("get reply 2", []*script.Event{sendReq2}, script.Recv{replyChan2, ConnectionState{false, "", 0}})
sendState := script.NewEvent("send state", []*script.Event{getReply2}, script.Send{controlChan, ConnectionState{true, "test", 1}})
getReply := script.NewEvent("get reply", []*script.Event{sendState}, script.Recv{replyChan, ConnectionState{true, "test", 1}})
err := script.Perform(0, []*script.Event{sendReq, sendReq2, getReply2, sendState, getReply})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestHandshakeAssembly(t *testing.T) {
_, requestChan, controlChan, recordChan, handshakeChan := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
_, requestChan, controlChan, recordChan, handshakeChan := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)

// Test the reassembly of a fragmented handshake message.
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("10000003")}});
send2 := script.NewEvent("send 2", []*script.Event{send1}, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("0001")}});
send3 := script.NewEvent("send 3", []*script.Event{send2}, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("42")}});
recvMsg := script.NewEvent("recv", []*script.Event{send3}, script.Recv{handshakeChan, &clientKeyExchangeMsg{fromHex("10000003000142"), fromHex("42")}});
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("10000003")}})
send2 := script.NewEvent("send 2", []*script.Event{send1}, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("0001")}})
send3 := script.NewEvent("send 3", []*script.Event{send2}, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("42")}})
recvMsg := script.NewEvent("recv", []*script.Event{send3}, script.Recv{handshakeChan, &clientKeyExchangeMsg{fromHex("10000003000142"), fromHex("42")}})

err := script.Perform(0, []*script.Event{send1, send2, send3, recvMsg});
err := script.Perform(0, []*script.Event{send1, send2, send3, recvMsg})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestEarlyApplicationData(t *testing.T) {
_, requestChan, controlChan, recordChan, handshakeChan := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
_, requestChan, controlChan, recordChan, handshakeChan := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)

// Test that applicaton data received before the handshake has completed results in an error.
send := script.NewEvent("send", nil, script.Send{recordChan, &record{recordTypeApplicationData, 0, 0, fromHex("")}});
recv := script.NewEvent("recv", []*script.Event{send}, script.Closed{handshakeChan});
send := script.NewEvent("send", nil, script.Send{recordChan, &record{recordTypeApplicationData, 0, 0, fromHex("")}})
recv := script.NewEvent("recv", []*script.Event{send}, script.Closed{handshakeChan})

err := script.Perform(0, []*script.Event{send, recv});
err := script.Perform(0, []*script.Event{send, recv})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestApplicationData(t *testing.T) {
appDataChan, requestChan, controlChan, recordChan, handshakeChan := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
appDataChan, requestChan, controlChan, recordChan, handshakeChan := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)

// Test that the application data is forwarded after a successful Finished message.
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("1400000c000000000000000000000000")}});
recv1 := script.NewEvent("recv finished", []*script.Event{send1}, script.Recv{handshakeChan, &finishedMsg{fromHex("1400000c000000000000000000000000"), fromHex("000000000000000000000000")}});
send2 := script.NewEvent("send connState", []*script.Event{recv1}, script.Send{controlChan, ConnectionState{true, "", 0}});
send3 := script.NewEvent("send 2", []*script.Event{send2}, script.Send{recordChan, &record{recordTypeApplicationData, 0, 0, fromHex("0102")}});
recv2 := script.NewEvent("recv data", []*script.Event{send3}, script.Recv{appDataChan, []byte{0x01, 0x02}});
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeHandshake, 0, 0, fromHex("1400000c000000000000000000000000")}})
recv1 := script.NewEvent("recv finished", []*script.Event{send1}, script.Recv{handshakeChan, &finishedMsg{fromHex("1400000c000000000000000000000000"), fromHex("000000000000000000000000")}})
send2 := script.NewEvent("send connState", []*script.Event{recv1}, script.Send{controlChan, ConnectionState{true, "", 0}})
send3 := script.NewEvent("send 2", []*script.Event{send2}, script.Send{recordChan, &record{recordTypeApplicationData, 0, 0, fromHex("0102")}})
recv2 := script.NewEvent("recv data", []*script.Event{send3}, script.Recv{appDataChan, []byte{0x01, 0x02}})

err := script.Perform(0, []*script.Event{send1, recv1, send2, send3, recv2});
err := script.Perform(0, []*script.Event{send1, recv1, send2, send3, recv2})
if err != nil {
t.Errorf("Got error: %s", err)
}
}

func TestInvalidChangeCipherSpec(t *testing.T) {
appDataChan, requestChan, controlChan, recordChan, handshakeChan := setup();
defer close(requestChan);
defer close(controlChan);
defer close(recordChan);
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeChangeCipherSpec, 0, 0, []byte{1}}});
recv1 := script.NewEvent("recv 1", []*script.Event{send1}, script.Recv{handshakeChan, changeCipherSpec{}});
send2 := script.NewEvent("send 2", []*script.Event{recv1}, script.Send{controlChan, ConnectionState{false, "", 42}});
close := script.NewEvent("close 1", []*script.Event{send2}, script.Closed{appDataChan});
close2 := script.NewEvent("close 2", []*script.Event{send2}, script.Closed{handshakeChan});
err := script.Perform(0, []*script.Event{send1, recv1, send2, close, close2});
appDataChan, requestChan, controlChan, recordChan, handshakeChan := setup()
defer close(requestChan)
defer close(controlChan)
defer close(recordChan)
send1 := script.NewEvent("send 1", nil, script.Send{recordChan, &record{recordTypeChangeCipherSpec, 0, 0, []byte{1}}})
recv1 := script.NewEvent("recv 1", []*script.Event{send1}, script.Recv{handshakeChan, changeCipherSpec{}})
send2 := script.NewEvent("send 2", []*script.Event{recv1}, script.Send{controlChan, ConnectionState{false, "", 42}})
close := script.NewEvent("close 1", []*script.Event{send2}, script.Closed{appDataChan})
close2 := script.NewEvent("close 2", []*script.Event{send2}, script.Closed{handshakeChan})
err := script.Perform(0, []*script.Event{send1, recv1, send2, close, close2})
if err != nil {
t.Errorf("Got error: %s", err)
}


+ 10
- 10
record_read.go ファイルの表示

@@ -9,34 +9,34 @@ package tls
// it's outbound channel. On error, it closes its outbound channel.

import (
"io";
"bufio";
"io"
"bufio"
)

// recordReader loops, reading TLS records from source and writing them to the
// given channel. The channel is closed on EOF or on error.
func recordReader(c chan<- *record, source io.Reader) {
defer close(c);
buf := bufio.NewReader(source);
defer close(c)
buf := bufio.NewReader(source)

for {
var header [5]byte;
n, _ := buf.Read(header[0:]);
var header [5]byte
n, _ := buf.Read(header[0:])
if n != 5 {
return
}

recordLength := int(header[3])<<8 | int(header[4]);
recordLength := int(header[3])<<8 | int(header[4])
if recordLength > maxTLSCiphertext {
return
}

payload := make([]byte, recordLength);
n, _ = buf.Read(payload);
payload := make([]byte, recordLength)
n, _ = buf.Read(payload)
if n != recordLength {
return
}

c <- &record{recordType(header[0]), header[1], header[2], payload};
c <- &record{recordType(header[0]), header[1], header[2], payload}
}
}

+ 19
- 19
record_read_test.go ファイルの表示

@@ -5,9 +5,9 @@
package tls

import (
"bytes";
"testing";
"testing/iotest";
"bytes"
"testing"
"testing/iotest"
)

func matchRecord(r1, r2 *record) bool {
@@ -20,12 +20,12 @@ func matchRecord(r1, r2 *record) bool {
return r1.contentType == r2.contentType &&
r1.major == r2.major &&
r1.minor == r2.minor &&
bytes.Compare(r1.payload, r2.payload) == 0;
bytes.Compare(r1.payload, r2.payload) == 0
}

type recordReaderTest struct {
in []byte;
out []*record;
in []byte
out []*record
}

var recordReaderTests = []recordReaderTest{
@@ -42,31 +42,31 @@ var recordReaderTests = []recordReaderTest{

func TestRecordReader(t *testing.T) {
for i, test := range recordReaderTests {
buf := bytes.NewBuffer(test.in);
c := make(chan *record);
go recordReader(c, buf);
matchRecordReaderOutput(t, i, test, c);
buf := bytes.NewBuffer(test.in)
c := make(chan *record)
go recordReader(c, buf)
matchRecordReaderOutput(t, i, test, c)

buf = bytes.NewBuffer(test.in);
buf2 := iotest.OneByteReader(buf);
c = make(chan *record);
go recordReader(c, buf2);
matchRecordReaderOutput(t, i*2, test, c);
buf = bytes.NewBuffer(test.in)
buf2 := iotest.OneByteReader(buf)
c = make(chan *record)
go recordReader(c, buf2)
matchRecordReaderOutput(t, i*2, test, c)
}
}

func matchRecordReaderOutput(t *testing.T, i int, test recordReaderTest, c <-chan *record) {
for j, r1 := range test.out {
r2 := <-c;
r2 := <-c
if r2 == nil {
t.Errorf("#%d truncated after %d values", i, j);
break;
t.Errorf("#%d truncated after %d values", i, j)
break
}
if !matchRecord(r1, r2) {
t.Errorf("#%d (%d) got:%#v want:%#v", i, j, r2, r1)
}
}
<-c;
<-c
if !closed(c) {
t.Errorf("#%d: channel didn't close", i)
}


+ 66
- 66
record_write.go ファイルの表示

@@ -5,9 +5,9 @@
package tls

import (
"fmt";
"hash";
"io";
"fmt"
"hash"
"io"
)

// writerEnableApplicationData is a message which instructs recordWriter to
@@ -17,14 +17,14 @@ type writerEnableApplicationData struct{}
// writerChangeCipherSpec updates the encryption and MAC functions and resets
// the sequence count.
type writerChangeCipherSpec struct {
encryptor encryptor;
mac hash.Hash;
encryptor encryptor
mac hash.Hash
}

// writerSetVersion sets the version number bytes that we included in the
// record header for future records.
type writerSetVersion struct {
major, minor uint8;
major, minor uint8
}

// A recordWriter accepts messages from the handshake processor and
@@ -32,37 +32,37 @@ type writerSetVersion struct {
// writing. It doesn't read from the application data channel until the
// handshake processor has signaled that the handshake is complete.
type recordWriter struct {
writer io.Writer;
encryptor encryptor;
mac hash.Hash;
seqNum uint64;
major, minor uint8;
shutdown bool;
appChan <-chan []byte;
controlChan <-chan interface{};
header [13]byte;
writer io.Writer
encryptor encryptor
mac hash.Hash
seqNum uint64
major, minor uint8
shutdown bool
appChan <-chan []byte
controlChan <-chan interface{}
header [13]byte
}

func (w *recordWriter) loop(writer io.Writer, appChan <-chan []byte, controlChan <-chan interface{}) {
w.writer = writer;
w.encryptor = nop{};
w.mac = nop{};
w.appChan = appChan;
w.controlChan = controlChan;
w.writer = writer
w.encryptor = nop{}
w.mac = nop{}
w.appChan = appChan
w.controlChan = controlChan

for !w.shutdown {
msg := <-controlChan;
msg := <-controlChan
if _, ok := msg.(writerEnableApplicationData); ok {
break
}
w.processControlMessage(msg);
w.processControlMessage(msg)
}

for !w.shutdown {
// Always process control messages first.
if controlMsg, ok := <-controlChan; ok {
w.processControlMessage(controlMsg);
continue;
w.processControlMessage(controlMsg)
continue
}

select {
@@ -89,58 +89,58 @@ func (w *recordWriter) loop(writer io.Writer, appChan <-chan []byte, controlChan

// fillMACHeader generates a MAC header. See RFC 4346, section 6.2.3.1.
func fillMACHeader(header *[13]byte, seqNum uint64, length int, r *record) {
header[0] = uint8(seqNum >> 56);
header[1] = uint8(seqNum >> 48);
header[2] = uint8(seqNum >> 40);
header[3] = uint8(seqNum >> 32);
header[4] = uint8(seqNum >> 24);
header[5] = uint8(seqNum >> 16);
header[6] = uint8(seqNum >> 8);
header[7] = uint8(seqNum);
header[8] = uint8(r.contentType);
header[9] = r.major;
header[10] = r.minor;
header[11] = uint8(length >> 8);
header[12] = uint8(length);
header[0] = uint8(seqNum >> 56)
header[1] = uint8(seqNum >> 48)
header[2] = uint8(seqNum >> 40)
header[3] = uint8(seqNum >> 32)
header[4] = uint8(seqNum >> 24)
header[5] = uint8(seqNum >> 16)
header[6] = uint8(seqNum >> 8)
header[7] = uint8(seqNum)
header[8] = uint8(r.contentType)
header[9] = r.major
header[10] = r.minor
header[11] = uint8(length >> 8)
header[12] = uint8(length)
}

func (w *recordWriter) writeRecord(r *record) {
w.mac.Reset();
w.mac.Reset()

fillMACHeader(&w.header, w.seqNum, len(r.payload), r);
fillMACHeader(&w.header, w.seqNum, len(r.payload), r)

w.mac.Write(w.header[0:13]);
w.mac.Write(r.payload);
macBytes := w.mac.Sum();
w.mac.Write(w.header[0:13])
w.mac.Write(r.payload)
macBytes := w.mac.Sum()

w.encryptor.XORKeyStream(r.payload);
w.encryptor.XORKeyStream(macBytes);
w.encryptor.XORKeyStream(r.payload)
w.encryptor.XORKeyStream(macBytes)

length := len(r.payload) + len(macBytes);
w.header[11] = uint8(length >> 8);
w.header[12] = uint8(length);
w.writer.Write(w.header[8:13]);
w.writer.Write(r.payload);
w.writer.Write(macBytes);
length := len(r.payload) + len(macBytes)
w.header[11] = uint8(length >> 8)
w.header[12] = uint8(length)
w.writer.Write(w.header[8:13])
w.writer.Write(r.payload)
w.writer.Write(macBytes)

w.seqNum++;
w.seqNum++
}

func (w *recordWriter) processControlMessage(controlMsg interface{}) {
if controlMsg == nil {
w.shutdown = true;
return;
w.shutdown = true
return
}

switch msg := controlMsg.(type) {
case writerChangeCipherSpec:
w.writeRecord(&record{recordTypeChangeCipherSpec, w.major, w.minor, []byte{0x01}});
w.encryptor = msg.encryptor;
w.mac = msg.mac;
w.seqNum = 0;
w.writeRecord(&record{recordTypeChangeCipherSpec, w.major, w.minor, []byte{0x01}})
w.encryptor = msg.encryptor
w.mac = msg.mac
w.seqNum = 0
case writerSetVersion:
w.major = msg.major;
w.minor = msg.minor;
w.major = msg.major
w.minor = msg.minor
case alert:
w.writeRecord(&record{recordTypeAlert, w.major, w.minor, []byte{byte(msg.level), byte(msg.error)}})
case handshakeMessage:
@@ -153,18 +153,18 @@ func (w *recordWriter) processControlMessage(controlMsg interface{}) {

func (w *recordWriter) processAppMessage(appMsg []byte) {
if closed(w.appChan) {
w.writeRecord(&record{recordTypeApplicationData, w.major, w.minor, []byte{byte(alertCloseNotify)}});
w.shutdown = true;
return;
w.writeRecord(&record{recordTypeApplicationData, w.major, w.minor, []byte{byte(alertCloseNotify)}})
w.shutdown = true
return
}

var done int;
var done int
for done < len(appMsg) {
todo := len(appMsg);
todo := len(appMsg)
if todo > maxTLSPlaintext {
todo = maxTLSPlaintext
}
w.writeRecord(&record{recordTypeApplicationData, w.major, w.minor, appMsg[done : done+todo]});
done += todo;
w.writeRecord(&record{recordTypeApplicationData, w.major, w.minor, appMsg[done : done+todo]})
done += todo
}
}

+ 70
- 70
tls.go ファイルの表示

@@ -6,26 +6,26 @@
package tls

import (
"io";
"os";
"net";
"time";
"io"
"os"
"net"
"time"
)

// A Conn represents a secure connection.
type Conn struct {
net.Conn;
writeChan chan<- []byte;
readChan <-chan []byte;
requestChan chan<- interface{};
readBuf []byte;
eof bool;
readTimeout, writeTimeout int64;
net.Conn
writeChan chan<- []byte
readChan <-chan []byte
requestChan chan<- interface{}
readBuf []byte
eof bool
readTimeout, writeTimeout int64
}

func timeout(c chan<- bool, nsecs int64) {
time.Sleep(nsecs);
c <- true;
time.Sleep(nsecs)
c <- true
}

func (tls *Conn) Read(p []byte) (int, os.Error) {
@@ -34,10 +34,10 @@ func (tls *Conn) Read(p []byte) (int, os.Error) {
return 0, os.EOF
}

var timeoutChan chan bool;
var timeoutChan chan bool
if tls.readTimeout > 0 {
timeoutChan = make(chan bool);
go timeout(timeoutChan, tls.readTimeout);
timeoutChan = make(chan bool)
go timeout(timeoutChan, tls.readTimeout)
}

select {
@@ -53,14 +53,14 @@ func (tls *Conn) Read(p []byte) (int, os.Error) {
return 0, io.ErrUnexpectedEOF
}
if len(tls.readBuf) == 0 {
tls.eof = true;
return 0, os.EOF;
tls.eof = true
return 0, os.EOF
}
}

n := copy(p, tls.readBuf);
tls.readBuf = tls.readBuf[n:];
return n, nil;
n := copy(p, tls.readBuf)
tls.readBuf = tls.readBuf[n:]
return n, nil
}

func (tls *Conn) Write(p []byte) (int, os.Error) {
@@ -68,10 +68,10 @@ func (tls *Conn) Write(p []byte) (int, os.Error) {
return 0, os.EOF
}

var timeoutChan chan bool;
var timeoutChan chan bool
if tls.writeTimeout > 0 {
timeoutChan = make(chan bool);
go timeout(timeoutChan, tls.writeTimeout);
timeoutChan = make(chan bool)
go timeout(timeoutChan, tls.writeTimeout)
}

select {
@@ -80,73 +80,73 @@ func (tls *Conn) Write(p []byte) (int, os.Error) {
return 0, os.EAGAIN
}

return len(p), nil;
return len(p), nil
}

func (tls *Conn) Close() os.Error {
close(tls.writeChan);
close(tls.requestChan);
tls.eof = true;
return nil;
close(tls.writeChan)
close(tls.requestChan)
tls.eof = true
return nil
}

func (tls *Conn) SetTimeout(nsec int64) os.Error {
tls.readTimeout = nsec;
tls.writeTimeout = nsec;
return nil;
tls.readTimeout = nsec
tls.writeTimeout = nsec
return nil
}

func (tls *Conn) SetReadTimeout(nsec int64) os.Error {
tls.readTimeout = nsec;
return nil;
tls.readTimeout = nsec
return nil
}

func (tls *Conn) SetWriteTimeout(nsec int64) os.Error {
tls.writeTimeout = nsec;
return nil;
tls.writeTimeout = nsec
return nil
}

func (tls *Conn) GetConnectionState() ConnectionState {
replyChan := make(chan ConnectionState);
tls.requestChan <- getConnectionState{replyChan};
return <-replyChan;
replyChan := make(chan ConnectionState)
tls.requestChan <- getConnectionState{replyChan}
return <-replyChan
}

func (tls *Conn) WaitConnectionState() ConnectionState {
replyChan := make(chan ConnectionState);
tls.requestChan <- waitConnectionState{replyChan};
return <-replyChan;
replyChan := make(chan ConnectionState)
tls.requestChan <- waitConnectionState{replyChan}
return <-replyChan
}

type handshaker interface {
loop(writeChan chan<- interface{}, controlChan chan<- interface{}, msgChan <-chan interface{}, config *Config);
loop(writeChan chan<- interface{}, controlChan chan<- interface{}, msgChan <-chan interface{}, config *Config)
}

// Server establishes a secure connection over the given connection and acts
// as a TLS server.
func startTLSGoroutines(conn net.Conn, h handshaker, config *Config) *Conn {
tls := new(Conn);
tls.Conn = conn;
tls := new(Conn)
tls.Conn = conn

writeChan := make(chan []byte);
readChan := make(chan []byte);
requestChan := make(chan interface{});
writeChan := make(chan []byte)
readChan := make(chan []byte)
requestChan := make(chan interface{})

tls.writeChan = writeChan;
tls.readChan = readChan;
tls.requestChan = requestChan;
tls.writeChan = writeChan
tls.readChan = readChan
tls.requestChan = requestChan

handshakeWriterChan := make(chan interface{});
processorHandshakeChan := make(chan interface{});
handshakeProcessorChan := make(chan interface{});
readerProcessorChan := make(chan *record);
handshakeWriterChan := make(chan interface{})
processorHandshakeChan := make(chan interface{})
handshakeProcessorChan := make(chan interface{})
readerProcessorChan := make(chan *record)

go new(recordWriter).loop(conn, writeChan, handshakeWriterChan);
go recordReader(readerProcessorChan, conn);
go new(recordProcessor).loop(readChan, requestChan, handshakeProcessorChan, readerProcessorChan, processorHandshakeChan);
go h.loop(handshakeWriterChan, handshakeProcessorChan, processorHandshakeChan, config);
go new(recordWriter).loop(conn, writeChan, handshakeWriterChan)
go recordReader(readerProcessorChan, conn)
go new(recordProcessor).loop(readChan, requestChan, handshakeProcessorChan, readerProcessorChan, processorHandshakeChan)
go h.loop(handshakeWriterChan, handshakeProcessorChan, processorHandshakeChan, config)

return tls;
return tls
}

func Server(conn net.Conn, config *Config) *Conn {
@@ -158,28 +158,28 @@ func Client(conn net.Conn, config *Config) *Conn {
}

type Listener struct {
listener net.Listener;
config *Config;
listener net.Listener
config *Config
}

func (l Listener) Accept() (c net.Conn, err os.Error) {
c, err = l.listener.Accept();
c, err = l.listener.Accept()
if err != nil {
return
}

c = Server(c, l.config);
return;
c = Server(c, l.config)
return
}

func (l Listener) Close() os.Error { return l.listener.Close() }
func (l Listener) Close() os.Error { return l.listener.Close() }

func (l Listener) Addr() net.Addr { return l.listener.Addr() }
func (l Listener) Addr() net.Addr { return l.listener.Addr() }

// NewListener creates a Listener which accepts connections from an inner
// Listener and wraps each connection with Server.
func NewListener(listener net.Listener, config *Config) (l Listener) {
l.listener = listener;
l.config = config;
return;
l.listener = listener
l.config = config
return
}

読み込み中…
キャンセル
保存