diff options
Diffstat (limited to 'src/pkg/crypto/tls/handshake_messages.go')
-rw-r--r-- | src/pkg/crypto/tls/handshake_messages.go | 148 |
1 files changed, 137 insertions, 11 deletions
diff --git a/src/pkg/crypto/tls/handshake_messages.go b/src/pkg/crypto/tls/handshake_messages.go index cdd491707..83952000f 100644 --- a/src/pkg/crypto/tls/handshake_messages.go +++ b/src/pkg/crypto/tls/handshake_messages.go @@ -20,6 +20,7 @@ type clientHelloMsg struct { supportedPoints []uint8 ticketSupported bool sessionTicket []uint8 + signatureAndHashes []signatureAndHash } func (m *clientHelloMsg) equal(i interface{}) bool { @@ -40,7 +41,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool { eqUint16s(m.supportedCurves, m1.supportedCurves) && bytes.Equal(m.supportedPoints, m1.supportedPoints) && m.ticketSupported == m1.ticketSupported && - bytes.Equal(m.sessionTicket, m1.sessionTicket) + bytes.Equal(m.sessionTicket, m1.sessionTicket) && + eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) } func (m *clientHelloMsg) marshal() []byte { @@ -74,6 +76,10 @@ func (m *clientHelloMsg) marshal() []byte { extensionsLength += len(m.sessionTicket) numExtensions++ } + if len(m.signatureAndHashes) > 0 { + extensionsLength += 2 + 2*len(m.signatureAndHashes) + numExtensions++ + } if numExtensions > 0 { extensionsLength += 4 * numExtensions length += 2 + extensionsLength @@ -199,6 +205,25 @@ func (m *clientHelloMsg) marshal() []byte { copy(z, m.sessionTicket) z = z[len(m.sessionTicket):] } + if len(m.signatureAndHashes) > 0 { + // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + z[0] = byte(extensionSignatureAlgorithms >> 8) + z[1] = byte(extensionSignatureAlgorithms) + l := 2 + 2*len(m.signatureAndHashes) + z[2] = byte(l >> 8) + z[3] = byte(l) + z = z[4:] + + l -= 2 + z[0] = byte(l >> 8) + z[1] = byte(l) + z = z[2:] + for _, sigAndHash := range m.signatureAndHashes { + z[0] = sigAndHash.hash + z[1] = sigAndHash.signature + z = z[2:] + } + } m.raw = x @@ -249,6 +274,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { m.ocspStapling = false m.ticketSupported = false m.sessionTicket = nil + m.signatureAndHashes = nil if len(data) == 0 { // ClientHello is optionally followed by extension data @@ -336,6 +362,23 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { // http://tools.ietf.org/html/rfc5077#section-3.2 m.ticketSupported = true m.sessionTicket = data[:length] + case extensionSignatureAlgorithms: + // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + if length < 2 || length&1 != 0 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l != length-2 { + return false + } + n := l / 2 + d := data[2:] + m.signatureAndHashes = make([]signatureAndHash, n) + for i := range m.signatureAndHashes { + m.signatureAndHashes[i].hash = d[0] + m.signatureAndHashes[i].signature = d[1] + d = d[2:] + } } data = data[length:] } @@ -899,8 +942,14 @@ func (m *nextProtoMsg) unmarshal(data []byte) bool { } type certificateRequestMsg struct { - raw []byte + raw []byte + // hasSignatureAndHash indicates whether this message includes a list + // of signature and hash functions. This change was introduced with TLS + // 1.2. + hasSignatureAndHash bool + certificateTypes []byte + signatureAndHashes []signatureAndHash certificateAuthorities [][]byte } @@ -912,7 +961,8 @@ func (m *certificateRequestMsg) equal(i interface{}) bool { return bytes.Equal(m.raw, m1.raw) && bytes.Equal(m.certificateTypes, m1.certificateTypes) && - eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) + eqByteSlices(m.certificateAuthorities, m1.certificateAuthorities) && + eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) } func (m *certificateRequestMsg) marshal() (x []byte) { @@ -928,6 +978,10 @@ func (m *certificateRequestMsg) marshal() (x []byte) { } length += casLength + if m.hasSignatureAndHash { + length += 2 + 2*len(m.signatureAndHashes) + } + x = make([]byte, 4+length) x[0] = typeCertificateRequest x[1] = uint8(length >> 16) @@ -938,6 +992,19 @@ func (m *certificateRequestMsg) marshal() (x []byte) { copy(x[5:], m.certificateTypes) y := x[5+len(m.certificateTypes):] + + if m.hasSignatureAndHash { + n := len(m.signatureAndHashes) * 2 + y[0] = uint8(n >> 8) + y[1] = uint8(n) + y = y[2:] + for _, sigAndHash := range m.signatureAndHashes { + y[0] = sigAndHash.hash + y[1] = sigAndHash.signature + y = y[2:] + } + } + y[0] = uint8(casLength >> 8) y[1] = uint8(casLength) y = y[2:] @@ -978,6 +1045,27 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { data = data[numCertTypes:] + if m.hasSignatureAndHash { + if len(data) < 2 { + return false + } + sigAndHashLen := uint16(data[0])<<8 | uint16(data[1]) + data = data[2:] + if sigAndHashLen&1 != 0 { + return false + } + if len(data) < int(sigAndHashLen) { + return false + } + numSigAndHash := sigAndHashLen / 2 + m.signatureAndHashes = make([]signatureAndHash, numSigAndHash) + for i := range m.signatureAndHashes { + m.signatureAndHashes[i].hash = data[0] + m.signatureAndHashes[i].signature = data[1] + data = data[2:] + } + } + if len(data) < 2 { return false } @@ -1013,8 +1101,10 @@ func (m *certificateRequestMsg) unmarshal(data []byte) bool { } type certificateVerifyMsg struct { - raw []byte - signature []byte + raw []byte + hasSignatureAndHash bool + signatureAndHash signatureAndHash + signature []byte } func (m *certificateVerifyMsg) equal(i interface{}) bool { @@ -1024,6 +1114,9 @@ func (m *certificateVerifyMsg) equal(i interface{}) bool { } return bytes.Equal(m.raw, m1.raw) && + m.hasSignatureAndHash == m1.hasSignatureAndHash && + m.signatureAndHash.hash == m1.signatureAndHash.hash && + m.signatureAndHash.signature == m1.signatureAndHash.signature && bytes.Equal(m.signature, m1.signature) } @@ -1035,14 +1128,23 @@ func (m *certificateVerifyMsg) marshal() (x []byte) { // See http://tools.ietf.org/html/rfc4346#section-7.4.8 siglength := len(m.signature) length := 2 + siglength + if m.hasSignatureAndHash { + length += 2 + } x = make([]byte, 4+length) x[0] = typeCertificateVerify x[1] = uint8(length >> 16) x[2] = uint8(length >> 8) x[3] = uint8(length) - x[4] = uint8(siglength >> 8) - x[5] = uint8(siglength) - copy(x[6:], m.signature) + y := x[4:] + if m.hasSignatureAndHash { + y[0] = m.signatureAndHash.hash + y[1] = m.signatureAndHash.signature + y = y[2:] + } + y[0] = uint8(siglength >> 8) + y[1] = uint8(siglength) + copy(y[2:], m.signature) m.raw = x @@ -1061,12 +1163,23 @@ func (m *certificateVerifyMsg) unmarshal(data []byte) bool { return false } - siglength := int(data[4])<<8 + int(data[5]) - if len(data)-6 != siglength { + data = data[4:] + if m.hasSignatureAndHash { + m.signatureAndHash.hash = data[0] + m.signatureAndHash.signature = data[1] + data = data[2:] + } + + if len(data) < 2 { + return false + } + siglength := int(data[0])<<8 + int(data[1]) + data = data[2:] + if len(data) != siglength { return false } - m.signature = data[6:] + m.signature = data return true } @@ -1165,3 +1278,16 @@ func eqByteSlices(x, y [][]byte) bool { } return true } + +func eqSignatureAndHashes(x, y []signatureAndHash) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + v2 := y[i] + if v.hash != v2.hash || v.signature != v2.signature { + return false + } + } + return true +} |