summaryrefslogtreecommitdiff
path: root/src/pkg/crypto/tls/common.go
blob: ef54a1db76363e29f07761915c20086dc417e068 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tls

import (
	"crypto/rand"
	"crypto/rsa"
	"io"
	"io/ioutil"
	"once"
	"os"
	"time"
)

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


// TLS record types.
type recordType uint8

const (
	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
	typeNextProtocol      uint8 = 67 // Not IANA assigned
)

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

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

// TLS extension numbers
var (
	extensionServerName   uint16 = 0
	extensionNextProtoNeg uint16 = 13172 // not IANA assigned
)

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

// 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
	// Time returns the current time as the number of seconds since the epoch.
	Time         func() int64
	Certificates []Certificate
	RootCAs      *CASet
	// NextProtos is a list of supported, application level protocols.
	// Currently only server-side handling is supported.
	NextProtos []string
}

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

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

type handshakeMessage interface {
	marshal() []byte
}

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

// mutualVersion returns the protocol version to use given the advertised
// version of the peer.
func mutualVersion(theirMajor, theirMinor uint8) (major, minor uint8, ok bool) {
	// We don't deal with peers < TLS 1.0 (aka version 3.1).
	if theirMajor < 3 || theirMajor == 3 && theirMinor < 1 {
		return 0, 0, false
	}
	major = 3
	minor = 2
	if theirMinor < minor {
		minor = theirMinor
	}
	ok = true
	return
}

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

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

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

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

func (nop) Reset() {}

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


// The defaultConfig is used in place of a nil *Config in the TLS server and client.
var varDefaultConfig *Config

func defaultConfig() *Config {
	once.Do(initDefaultConfig)
	return varDefaultConfig
}

// Possible certificate files; stop after finding one.
// On OS X we should really be using the Directory Services keychain
// but that requires a lot of Mach goo to get at.  Instead we use
// the same root set that curl uses.
var certFiles = []string{
	"/etc/ssl/certs/ca-certificates.crt", // Linux etc
	"/usr/share/curl/curl-ca-bundle.crt", // OS X
}

func initDefaultConfig() {
	roots := NewCASet()
	for _, file := range certFiles {
		data, err := ioutil.ReadFile(file)
		if err == nil {
			roots.SetFromPEM(data)
			break
		}
	}

	varDefaultConfig = &Config{
		Rand:    rand.Reader,
		Time:    time.Seconds,
		RootCAs: roots,
	}
}