URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [crypto/] [tls/] [prf.go] - Rev 747
Compare with Previous | Blame | View Log
// 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 ("crypto/hmac""crypto/md5""crypto/sha1""hash")// 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}// pHash implements the P_hash function, as defined in RFC 4346, section 5.func pHash(result, secret, seed []byte, hash func() hash.Hash) {h := hmac.New(hash, secret)h.Write(seed)a := h.Sum(nil)j := 0for j < len(result) {h.Reset()h.Write(a)h.Write(seed)b := h.Sum(nil)todo := len(b)if j+todo > len(result) {todo = len(result) - j}copy(result[j:j+todo], b)j += todoh.Reset()h.Write(a)a = h.Sum(nil)}}// pRF10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.func pRF10(result, secret, label, seed []byte) {hashSHA1 := sha1.NewhashMD5 := md5.NewlabelAndSeed := 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)for i, b := range result2 {result[i] ^= b}}// pRF30 implements the SSL 3.0 pseudo-random function, as defined in// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.func pRF30(result, secret, label, seed []byte) {hashSHA1 := sha1.New()hashMD5 := md5.New()done := 0i := 0// RFC5246 section 6.3 says that the largest PRF output needed is 128// bytes. Since no more ciphersuites will be added to SSLv3, this will// remain true. Each iteration gives us 16 bytes so 10 iterations will// be sufficient.var b [11]bytefor done < len(result) {for j := 0; j <= i; j++ {b[j] = 'A' + byte(i)}hashSHA1.Reset()hashSHA1.Write(b[:i+1])hashSHA1.Write(secret)hashSHA1.Write(seed)digest := hashSHA1.Sum(nil)hashMD5.Reset()hashMD5.Write(secret)hashMD5.Write(digest)done += copy(result[done:], hashMD5.Sum(nil))i++}}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.)var masterSecretLabel = []byte("master secret")var keyExpansionLabel = []byte("key expansion")var clientFinishedLabel = []byte("client finished")var serverFinishedLabel = []byte("server finished")// keysFromPreMasterSecret generates the connection keys from the pre master// secret, given the lengths of the MAC key, cipher key and IV, as defined in// RFC 2246, section 6.3.func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {prf := pRF10if version == versionSSL30 {prf = pRF30}var seed [tlsRandomLength * 2]bytecopy(seed[0:len(clientRandom)], clientRandom)copy(seed[len(clientRandom):], serverRandom)masterSecret = make([]byte, masterSecretLength)prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])copy(seed[0:len(clientRandom)], serverRandom)copy(seed[len(serverRandom):], clientRandom)n := 2*macLen + 2*keyLen + 2*ivLenkeyMaterial := make([]byte, n)prf(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])clientMAC = keyMaterial[:macLen]keyMaterial = keyMaterial[macLen:]serverMAC = keyMaterial[:macLen]keyMaterial = keyMaterial[macLen:]clientKey = keyMaterial[:keyLen]keyMaterial = keyMaterial[keyLen:]serverKey = keyMaterial[:keyLen]keyMaterial = keyMaterial[keyLen:]clientIV = keyMaterial[:ivLen]keyMaterial = keyMaterial[ivLen:]serverIV = keyMaterial[:ivLen]return}func newFinishedHash(version uint16) finishedHash {return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New(), version}}// A finishedHash calculates the hash of a set of handshake messages suitable// for including in a Finished message.type finishedHash struct {clientMD5 hash.HashclientSHA1 hash.HashserverMD5 hash.HashserverSHA1 hash.Hashversion uint16}func (h finishedHash) Write(msg []byte) (n int, err error) {h.clientMD5.Write(msg)h.clientSHA1.Write(msg)h.serverMD5.Write(msg)h.serverSHA1.Write(msg)return len(msg), nil}// finishedSum10 calculates the contents of the verify_data member of a TLSv1// Finished message given the MD5 and SHA1 hashes of a set of handshake// messages.func finishedSum10(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)pRF10(out, masterSecret, label, seed)return out}// finishedSum30 calculates the contents of the verify_data member of a SSLv3// Finished message given the MD5 and SHA1 hashes of a set of handshake// messages.func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {md5.Write(magic[:])md5.Write(masterSecret)md5.Write(ssl30Pad1[:])md5Digest := md5.Sum(nil)md5.Reset()md5.Write(masterSecret)md5.Write(ssl30Pad2[:])md5.Write(md5Digest)md5Digest = md5.Sum(nil)sha1.Write(magic[:])sha1.Write(masterSecret)sha1.Write(ssl30Pad1[:40])sha1Digest := sha1.Sum(nil)sha1.Reset()sha1.Write(masterSecret)sha1.Write(ssl30Pad2[:40])sha1.Write(sha1Digest)sha1Digest = sha1.Sum(nil)ret := make([]byte, len(md5Digest)+len(sha1Digest))copy(ret, md5Digest)copy(ret[len(md5Digest):], sha1Digest)return ret}var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}// clientSum returns the contents of the verify_data member of a client's// Finished message.func (h finishedHash) clientSum(masterSecret []byte) []byte {if h.version == versionSSL30 {return finishedSum30(h.clientMD5, h.clientSHA1, masterSecret, ssl3ClientFinishedMagic)}md5 := h.clientMD5.Sum(nil)sha1 := h.clientSHA1.Sum(nil)return finishedSum10(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 {if h.version == versionSSL30 {return finishedSum30(h.serverMD5, h.serverSHA1, masterSecret, ssl3ServerFinishedMagic)}md5 := h.serverMD5.Sum(nil)sha1 := h.serverSHA1.Sum(nil)return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret)}
