...

Source file src/crypto/tls/key_schedule.go

Documentation: crypto/tls

		 1  // Copyright 2018 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package tls
		 6  
		 7  import (
		 8  	"crypto/elliptic"
		 9  	"crypto/hmac"
		10  	"errors"
		11  	"hash"
		12  	"io"
		13  	"math/big"
		14  
		15  	"golang.org/x/crypto/cryptobyte"
		16  	"golang.org/x/crypto/curve25519"
		17  	"golang.org/x/crypto/hkdf"
		18  )
		19  
		20  // This file contains the functions necessary to compute the TLS 1.3 key
		21  // schedule. See RFC 8446, Section 7.
		22  
		23  const (
		24  	resumptionBinderLabel				 = "res binder"
		25  	clientHandshakeTrafficLabel	 = "c hs traffic"
		26  	serverHandshakeTrafficLabel	 = "s hs traffic"
		27  	clientApplicationTrafficLabel = "c ap traffic"
		28  	serverApplicationTrafficLabel = "s ap traffic"
		29  	exporterLabel								 = "exp master"
		30  	resumptionLabel							 = "res master"
		31  	trafficUpdateLabel						= "traffic upd"
		32  )
		33  
		34  // expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
		35  func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
		36  	var hkdfLabel cryptobyte.Builder
		37  	hkdfLabel.AddUint16(uint16(length))
		38  	hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
		39  		b.AddBytes([]byte("tls13 "))
		40  		b.AddBytes([]byte(label))
		41  	})
		42  	hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
		43  		b.AddBytes(context)
		44  	})
		45  	out := make([]byte, length)
		46  	n, err := hkdf.Expand(c.hash.New, secret, hkdfLabel.BytesOrPanic()).Read(out)
		47  	if err != nil || n != length {
		48  		panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
		49  	}
		50  	return out
		51  }
		52  
		53  // deriveSecret implements Derive-Secret from RFC 8446, Section 7.1.
		54  func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte {
		55  	if transcript == nil {
		56  		transcript = c.hash.New()
		57  	}
		58  	return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size())
		59  }
		60  
		61  // extract implements HKDF-Extract with the cipher suite hash.
		62  func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
		63  	if newSecret == nil {
		64  		newSecret = make([]byte, c.hash.Size())
		65  	}
		66  	return hkdf.Extract(c.hash.New, newSecret, currentSecret)
		67  }
		68  
		69  // nextTrafficSecret generates the next traffic secret, given the current one,
		70  // according to RFC 8446, Section 7.2.
		71  func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte {
		72  	return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size())
		73  }
		74  
		75  // trafficKey generates traffic keys according to RFC 8446, Section 7.3.
		76  func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
		77  	key = c.expandLabel(trafficSecret, "key", nil, c.keyLen)
		78  	iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength)
		79  	return
		80  }
		81  
		82  // finishedHash generates the Finished verify_data or PskBinderEntry according
		83  // to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey
		84  // selection.
		85  func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte {
		86  	finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size())
		87  	verifyData := hmac.New(c.hash.New, finishedKey)
		88  	verifyData.Write(transcript.Sum(nil))
		89  	return verifyData.Sum(nil)
		90  }
		91  
		92  // exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to
		93  // RFC 8446, Section 7.5.
		94  func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) {
		95  	expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript)
		96  	return func(label string, context []byte, length int) ([]byte, error) {
		97  		secret := c.deriveSecret(expMasterSecret, label, nil)
		98  		h := c.hash.New()
		99  		h.Write(context)
	 100  		return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil
	 101  	}
	 102  }
	 103  
	 104  // ecdheParameters implements Diffie-Hellman with either NIST curves or X25519,
	 105  // according to RFC 8446, Section 4.2.8.2.
	 106  type ecdheParameters interface {
	 107  	CurveID() CurveID
	 108  	PublicKey() []byte
	 109  	SharedKey(peerPublicKey []byte) []byte
	 110  }
	 111  
	 112  func generateECDHEParameters(rand io.Reader, curveID CurveID) (ecdheParameters, error) {
	 113  	if curveID == X25519 {
	 114  		privateKey := make([]byte, curve25519.ScalarSize)
	 115  		if _, err := io.ReadFull(rand, privateKey); err != nil {
	 116  			return nil, err
	 117  		}
	 118  		publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
	 119  		if err != nil {
	 120  			return nil, err
	 121  		}
	 122  		return &x25519Parameters{privateKey: privateKey, publicKey: publicKey}, nil
	 123  	}
	 124  
	 125  	curve, ok := curveForCurveID(curveID)
	 126  	if !ok {
	 127  		return nil, errors.New("tls: internal error: unsupported curve")
	 128  	}
	 129  
	 130  	p := &nistParameters{curveID: curveID}
	 131  	var err error
	 132  	p.privateKey, p.x, p.y, err = elliptic.GenerateKey(curve, rand)
	 133  	if err != nil {
	 134  		return nil, err
	 135  	}
	 136  	return p, nil
	 137  }
	 138  
	 139  func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
	 140  	switch id {
	 141  	case CurveP256:
	 142  		return elliptic.P256(), true
	 143  	case CurveP384:
	 144  		return elliptic.P384(), true
	 145  	case CurveP521:
	 146  		return elliptic.P521(), true
	 147  	default:
	 148  		return nil, false
	 149  	}
	 150  }
	 151  
	 152  type nistParameters struct {
	 153  	privateKey []byte
	 154  	x, y			 *big.Int // public key
	 155  	curveID		CurveID
	 156  }
	 157  
	 158  func (p *nistParameters) CurveID() CurveID {
	 159  	return p.curveID
	 160  }
	 161  
	 162  func (p *nistParameters) PublicKey() []byte {
	 163  	curve, _ := curveForCurveID(p.curveID)
	 164  	return elliptic.Marshal(curve, p.x, p.y)
	 165  }
	 166  
	 167  func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
	 168  	curve, _ := curveForCurveID(p.curveID)
	 169  	// Unmarshal also checks whether the given point is on the curve.
	 170  	x, y := elliptic.Unmarshal(curve, peerPublicKey)
	 171  	if x == nil {
	 172  		return nil
	 173  	}
	 174  
	 175  	xShared, _ := curve.ScalarMult(x, y, p.privateKey)
	 176  	sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
	 177  	return xShared.FillBytes(sharedKey)
	 178  }
	 179  
	 180  type x25519Parameters struct {
	 181  	privateKey []byte
	 182  	publicKey	[]byte
	 183  }
	 184  
	 185  func (p *x25519Parameters) CurveID() CurveID {
	 186  	return X25519
	 187  }
	 188  
	 189  func (p *x25519Parameters) PublicKey() []byte {
	 190  	return p.publicKey[:]
	 191  }
	 192  
	 193  func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte {
	 194  	sharedKey, err := curve25519.X25519(p.privateKey, peerPublicKey)
	 195  	if err != nil {
	 196  		return nil
	 197  	}
	 198  	return sharedKey
	 199  }
	 200  

View as plain text