// 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 tlsimport ()type prfFunc func(secret []byte, label string, seed []byte, keyLen int) []byte// Split a premaster secret in two as specified in RFC 4346, Section 5.func splitPreMasterSecret( []byte) (, []byte) { = [0 : (len()+1)/2] = [len()/2:]return}// pHash implements the P_hash function, as defined in RFC 4346, Section 5.func pHash(, , []byte, func() hash.Hash) { := hmac.New(, ) .Write() := .Sum(nil) := 0for < len() { .Reset() .Write() .Write() := .Sum(nil)copy([:], ) += len() .Reset() .Write() = .Sum(nil) }}// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5.func prf10( []byte, string, []byte, int) []byte { := make([]byte, ) := sha1.New := md5.New := make([]byte, len()+len())copy(, )copy([len():], ) , := splitPreMasterSecret()pHash(, , , ) := make([]byte, len())pHash(, , , )for , := range { [] ^= }return}// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5.func prf12( func() hash.Hash) prfFunc {returnfunc( []byte, string, []byte, int) []byte {returntls12.PRF(, , , , ) }}const ( masterSecretLength = 48// Length of a master secret in TLS 1.1. finishedVerifyLength = 12// Length of verify_data in a Finished message.)const masterSecretLabel = "master secret"const extendedMasterSecretLabel = "extended master secret"const keyExpansionLabel = "key expansion"const clientFinishedLabel = "client finished"const serverFinishedLabel = "server finished"func prfAndHashForVersion( uint16, *cipherSuite) (prfFunc, crypto.Hash) {switch {caseVersionTLS10, VersionTLS11:returnprf10, crypto.Hash(0)caseVersionTLS12:if .flags&suiteSHA384 != 0 {returnprf12(sha512.New384), crypto.SHA384 }returnprf12(sha256.New), crypto.SHA256default:panic("unknown version") }}func prfForVersion( uint16, *cipherSuite) prfFunc { , := prfAndHashForVersion(, )return}// masterFromPreMasterSecret generates the master secret from the pre-master// secret. See RFC 5246, Section 8.1.func masterFromPreMasterSecret( uint16, *cipherSuite, , , []byte) []byte { := make([]byte, 0, len()+len()) = append(, ...) = append(, ...)returnprfForVersion(, )(, masterSecretLabel, , masterSecretLength)}// extMasterFromPreMasterSecret generates the extended master secret from the// pre-master secret. See RFC 7627.func extMasterFromPreMasterSecret( uint16, *cipherSuite, , []byte) []byte { , := prfAndHashForVersion(, )if == VersionTLS12 {// Use the FIPS 140-3 module only for TLS 1.2 with EMS, which is the // only TLS 1.0-1.2 approved mode per IG D.Q.returntls12.MasterSecret(.New, , ) }return (, extendedMasterSecretLabel, , masterSecretLength)}// keysFromMasterSecret generates the connection keys from the master// secret, given the lengths of the MAC key, cipher key and IV, as defined in// RFC 2246, Section 6.3.func keysFromMasterSecret( uint16, *cipherSuite, , , []byte, , , int) (, , , , , []byte) { := make([]byte, 0, len()+len()) = append(, ...) = append(, ...) := 2* + 2* + 2* := prfForVersion(, )(, keyExpansionLabel, , ) = [:] = [:] = [:] = [:] = [:] = [:] = [:] = [:] = [:] = [:] = [:]return}func newFinishedHash( uint16, *cipherSuite) finishedHash {var []byteif >= VersionTLS12 { = []byte{} } , := prfAndHashForVersion(, )if != 0 {returnfinishedHash{.New(), .New(), nil, nil, , , } }returnfinishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), , , }}// A finishedHash calculates the hash of a set of handshake messages suitable// for including in a Finished message.type finishedHash struct { client hash.Hash server hash.Hash// Prior to TLS 1.2, an additional MD5 hash is required. clientMD5 hash.Hash serverMD5 hash.Hash// In TLS 1.2, a full buffer is sadly required. buffer []byte version uint16 prf prfFunc}func ( *finishedHash) ( []byte) ( int, error) { .client.Write() .server.Write()if .version < VersionTLS12 { .clientMD5.Write() .serverMD5.Write() }if .buffer != nil { .buffer = append(.buffer, ...) }returnlen(), nil}func ( finishedHash) () []byte {if .version >= VersionTLS12 {return .client.Sum(nil) } := make([]byte, 0, md5.Size+sha1.Size) = .clientMD5.Sum()return .client.Sum()}// clientSum returns the contents of the verify_data member of a client's// Finished message.func ( finishedHash) ( []byte) []byte {return .prf(, clientFinishedLabel, .Sum(), finishedVerifyLength)}// serverSum returns the contents of the verify_data member of a server's// Finished message.func ( finishedHash) ( []byte) []byte {return .prf(, serverFinishedLabel, .Sum(), finishedVerifyLength)}// hashForClientCertificate returns the handshake messages so far, pre-hashed,// suitable for signing by a TLS 1.0 and 1.1 client certificate.func ( finishedHash) ( uint8) []byte {if == signatureECDSA {return .server.Sum(nil) }return .Sum()}// discardHandshakeBuffer is called when there is no more need to// buffer the entirety of the handshake messages.func ( *finishedHash) () { .buffer = nil}// noEKMBecauseRenegotiation is used as a value of// ConnectionState.ekm when renegotiation is enabled and thus// we wish to fail all key-material export requests.func noEKMBecauseRenegotiation( string, []byte, int) ([]byte, error) {returnnil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled")}// noEKMBecauseNoEMS is used as a value of ConnectionState.ekm when Extended// Master Secret is not negotiated and thus we wish to fail all key-material// export requests.func noEKMBecauseNoEMS( string, []byte, int) ([]byte, error) {returnnil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when neither TLS 1.3 nor Extended Master Secret are negotiated; override with GODEBUG=tlsunsafeekm=1")}// ekmFromMasterSecret generates exported keying material as defined in RFC 5705.func ekmFromMasterSecret( uint16, *cipherSuite, , , []byte) func(string, []byte, int) ([]byte, error) {returnfunc( string, []byte, int) ([]byte, error) {switch {case"client finished", "server finished", "master secret", "key expansion":// These values are reserved and may not be used.returnnil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", ) } := len() + len()if != nil { += 2 + len() } := make([]byte, 0, ) = append(, ...) = append(, ...)if != nil {iflen() >= 1<<16 {returnnil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") } = append(, byte(len()>>8), byte(len())) = append(, ...) }returnprfForVersion(, )(, , , ), nil }}
The pages are generated with Goldsv0.8.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.