package tls
import (
)
func ( []byte) (, []byte) {
= [0 : (len()+1)/2]
= [len()/2:]
return
}
func (, , []byte, func() hash.Hash) {
:= hmac.New(, )
.Write()
:= .Sum(nil)
:= 0
for < len() {
.Reset()
.Write()
.Write()
:= .Sum(nil)
copy([:], )
+= len()
.Reset()
.Write()
= .Sum(nil)
}
}
func (, , , []byte) {
:= sha1.New
:= md5.New
:= make([]byte, len()+len())
copy(, )
copy([len():], )
, := splitPreMasterSecret()
pHash(, , , )
:= make([]byte, len())
pHash(, , , )
for , := range {
[] ^=
}
}
func ( func() hash.Hash) func(, , , []byte) {
return func(, , , []byte) {
:= make([]byte, len()+len())
copy(, )
copy([len():], )
pHash(, , , )
}
}
const (
masterSecretLength = 48
finishedVerifyLength = 12
)
var masterSecretLabel = []byte("master secret")
var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
func ( uint16, *cipherSuite) (func(, , , []byte), crypto.Hash) {
switch {
case VersionTLS10, VersionTLS11:
return prf10, crypto.Hash(0)
case VersionTLS12:
if .flags&suiteSHA384 != 0 {
return prf12(sha512.New384), crypto.SHA384
}
return prf12(sha256.New), crypto.SHA256
default:
panic("unknown version")
}
}
func ( uint16, *cipherSuite) func(, , , []byte) {
, := prfAndHashForVersion(, )
return
}
func ( uint16, *cipherSuite, , , []byte) []byte {
:= make([]byte, 0, len()+len())
= append(, ...)
= append(, ...)
:= make([]byte, masterSecretLength)
prfForVersion(, )(, , masterSecretLabel, )
return
}
func ( uint16, *cipherSuite, , , []byte, , , int) (, , , , , []byte) {
:= make([]byte, 0, len()+len())
= append(, ...)
= append(, ...)
:= 2* + 2* + 2*
:= make([]byte, )
prfForVersion(, )(, , keyExpansionLabel, )
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
= [:]
return
}
func ( uint16, *cipherSuite) finishedHash {
var []byte
if >= VersionTLS12 {
= []byte{}
}
, := prfAndHashForVersion(, )
if != 0 {
return finishedHash{.New(), .New(), nil, nil, , , }
}
return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), , , }
}
type finishedHash struct {
client hash.Hash
server hash.Hash
clientMD5 hash.Hash
serverMD5 hash.Hash
buffer []byte
version uint16
prf func(result, secret, label, seed []byte)
}
func ( *finishedHash) ( []byte) ( int, error) {
.client.Write()
.server.Write()
if .version < VersionTLS12 {
.clientMD5.Write()
.serverMD5.Write()
}
if .buffer != nil {
.buffer = append(.buffer, ...)
}
return len(), nil
}
func ( finishedHash) () []byte {
if .version >= VersionTLS12 {
return .client.Sum(nil)
}
:= make([]byte, 0, md5.Size+sha1.Size)
= .clientMD5.Sum()
return .client.Sum()
}
func ( finishedHash) ( []byte) []byte {
:= make([]byte, finishedVerifyLength)
.prf(, , clientFinishedLabel, .Sum())
return
}
func ( finishedHash) ( []byte) []byte {
:= make([]byte, finishedVerifyLength)
.prf(, , serverFinishedLabel, .Sum())
return
}
func ( finishedHash) ( uint8, crypto.Hash, []byte) []byte {
if (.version >= VersionTLS12 || == signatureEd25519) && .buffer == nil {
panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer")
}
if == signatureEd25519 {
return .buffer
}
if .version >= VersionTLS12 {
:= .New()
.Write(.buffer)
return .Sum(nil)
}
if == signatureECDSA {
return .server.Sum(nil)
}
return .Sum()
}
func ( *finishedHash) () {
.buffer = nil
}
func ( string, []byte, int) ([]byte, error) {
return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")
}
func ( uint16, *cipherSuite, , , []byte) func(string, []byte, int) ([]byte, error) {
return func( string, []byte, int) ([]byte, error) {
switch {
case "client finished", "server finished", "master secret", "key expansion":
return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", )
}
:= len() + len()
if != nil {
+= 2 + len()
}
:= make([]byte, 0, )
= append(, ...)
= append(, ...)
if != nil {
if len() >= 1<<16 {
return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long")
}
= append(, byte(len()>>8), byte(len()))
= append(, ...)
}
:= make([]byte, )
prfForVersion(, )(, , []byte(), )
return , nil
}
}