git.prognetwork.ru/x0r/utls@v1.3.3/key_schedule.go (about)

     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  	"fmt"
    12  	"hash"
    13  	"io"
    14  	"math/big"
    15  
    16  	"golang.org/x/crypto/cryptobyte"
    17  	"golang.org/x/crypto/curve25519"
    18  	"golang.org/x/crypto/hkdf"
    19  )
    20  
    21  // This file contains the functions necessary to compute the TLS 1.3 key
    22  // schedule. See RFC 8446, Section 7.
    23  
    24  const (
    25  	resumptionBinderLabel         = "res binder"
    26  	clientHandshakeTrafficLabel   = "c hs traffic"
    27  	serverHandshakeTrafficLabel   = "s hs traffic"
    28  	clientApplicationTrafficLabel = "c ap traffic"
    29  	serverApplicationTrafficLabel = "s ap traffic"
    30  	exporterLabel                 = "exp master"
    31  	resumptionLabel               = "res master"
    32  	trafficUpdateLabel            = "traffic upd"
    33  )
    34  
    35  // expandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1.
    36  func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []byte, length int) []byte {
    37  	var hkdfLabel cryptobyte.Builder
    38  	hkdfLabel.AddUint16(uint16(length))
    39  	hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
    40  		b.AddBytes([]byte("tls13 "))
    41  		b.AddBytes([]byte(label))
    42  	})
    43  	hkdfLabel.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
    44  		b.AddBytes(context)
    45  	})
    46  	hkdfLabelBytes, err := hkdfLabel.Bytes()
    47  	if err != nil {
    48  		// Rather than calling BytesOrPanic, we explicitly handle this error, in
    49  		// order to provide a reasonable error message. It should be basically
    50  		// impossible for this to panic, and routing errors back through the
    51  		// tree rooted in this function is quite painful. The labels are fixed
    52  		// size, and the context is either a fixed-length computed hash, or
    53  		// parsed from a field which has the same length limitation. As such, an
    54  		// error here is likely to only be caused during development.
    55  		//
    56  		// NOTE: another reasonable approach here might be to return a
    57  		// randomized slice if we encounter an error, which would break the
    58  		// connection, but avoid panicking. This would perhaps be safer but
    59  		// significantly more confusing to users.
    60  		panic(fmt.Errorf("failed to construct HKDF label: %s", err))
    61  	}
    62  	out := make([]byte, length)
    63  	n, err := hkdf.Expand(c.hash.New, secret, hkdfLabelBytes).Read(out)
    64  	if err != nil || n != length {
    65  		panic("tls: HKDF-Expand-Label invocation failed unexpectedly")
    66  	}
    67  	return out
    68  }
    69  
    70  // deriveSecret implements Derive-Secret from RFC 8446, Section 7.1.
    71  func (c *cipherSuiteTLS13) deriveSecret(secret []byte, label string, transcript hash.Hash) []byte {
    72  	if transcript == nil {
    73  		transcript = c.hash.New()
    74  	}
    75  	return c.expandLabel(secret, label, transcript.Sum(nil), c.hash.Size())
    76  }
    77  
    78  // extract implements HKDF-Extract with the cipher suite hash.
    79  func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte {
    80  	if newSecret == nil {
    81  		newSecret = make([]byte, c.hash.Size())
    82  	}
    83  	return hkdf.Extract(c.hash.New, newSecret, currentSecret)
    84  }
    85  
    86  // nextTrafficSecret generates the next traffic secret, given the current one,
    87  // according to RFC 8446, Section 7.2.
    88  func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte {
    89  	return c.expandLabel(trafficSecret, trafficUpdateLabel, nil, c.hash.Size())
    90  }
    91  
    92  // trafficKey generates traffic keys according to RFC 8446, Section 7.3.
    93  func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) {
    94  	key = c.expandLabel(trafficSecret, "key", nil, c.keyLen)
    95  	iv = c.expandLabel(trafficSecret, "iv", nil, aeadNonceLength)
    96  	return
    97  }
    98  
    99  // finishedHash generates the Finished verify_data or PskBinderEntry according
   100  // to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey
   101  // selection.
   102  func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte {
   103  	finishedKey := c.expandLabel(baseKey, "finished", nil, c.hash.Size())
   104  	verifyData := hmac.New(c.hash.New, finishedKey)
   105  	verifyData.Write(transcript.Sum(nil))
   106  	return verifyData.Sum(nil)
   107  }
   108  
   109  // exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to
   110  // RFC 8446, Section 7.5.
   111  func (c *cipherSuiteTLS13) exportKeyingMaterial(masterSecret []byte, transcript hash.Hash) func(string, []byte, int) ([]byte, error) {
   112  	expMasterSecret := c.deriveSecret(masterSecret, exporterLabel, transcript)
   113  	return func(label string, context []byte, length int) ([]byte, error) {
   114  		secret := c.deriveSecret(expMasterSecret, label, nil)
   115  		h := c.hash.New()
   116  		h.Write(context)
   117  		return c.expandLabel(secret, "exporter", h.Sum(nil), length), nil
   118  	}
   119  }
   120  
   121  // ecdheParameters implements Diffie-Hellman with either NIST curves or X25519,
   122  // according to RFC 8446, Section 4.2.8.2.
   123  type ecdheParameters interface {
   124  	CurveID() CurveID
   125  	PublicKey() []byte
   126  	SharedKey(peerPublicKey []byte) []byte
   127  }
   128  
   129  func generateECDHEParameters(rand io.Reader, curveID CurveID) (ecdheParameters, error) {
   130  	if curveID == X25519 {
   131  		privateKey := make([]byte, curve25519.ScalarSize)
   132  		if _, err := io.ReadFull(rand, privateKey); err != nil {
   133  			return nil, err
   134  		}
   135  		publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  		return &x25519Parameters{privateKey: privateKey, publicKey: publicKey}, nil
   140  	}
   141  
   142  	curve, ok := curveForCurveID(curveID)
   143  	if !ok {
   144  		return nil, errors.New("tls: internal error: unsupported curve")
   145  	}
   146  
   147  	p := &nistParameters{curveID: curveID}
   148  	var err error
   149  	p.privateKey, p.x, p.y, err = elliptic.GenerateKey(curve, rand)
   150  	if err != nil {
   151  		return nil, err
   152  	}
   153  	return p, nil
   154  }
   155  
   156  func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
   157  	switch id {
   158  	case CurveP256:
   159  		return elliptic.P256(), true
   160  	case CurveP384:
   161  		return elliptic.P384(), true
   162  	case CurveP521:
   163  		return elliptic.P521(), true
   164  	default:
   165  		return nil, false
   166  	}
   167  }
   168  
   169  type nistParameters struct {
   170  	privateKey []byte
   171  	x, y       *big.Int // public key
   172  	curveID    CurveID
   173  }
   174  
   175  func (p *nistParameters) CurveID() CurveID {
   176  	return p.curveID
   177  }
   178  
   179  func (p *nistParameters) PublicKey() []byte {
   180  	curve, _ := curveForCurveID(p.curveID)
   181  	return elliptic.Marshal(curve, p.x, p.y)
   182  }
   183  
   184  func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
   185  	curve, _ := curveForCurveID(p.curveID)
   186  	// Unmarshal also checks whether the given point is on the curve.
   187  	x, y := elliptic.Unmarshal(curve, peerPublicKey)
   188  	if x == nil {
   189  		return nil
   190  	}
   191  
   192  	xShared, _ := curve.ScalarMult(x, y, p.privateKey)
   193  	sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
   194  	return xShared.FillBytes(sharedKey)
   195  }
   196  
   197  type x25519Parameters struct {
   198  	privateKey []byte
   199  	publicKey  []byte
   200  }
   201  
   202  func (p *x25519Parameters) CurveID() CurveID {
   203  	return X25519
   204  }
   205  
   206  func (p *x25519Parameters) PublicKey() []byte {
   207  	return p.publicKey[:]
   208  }
   209  
   210  func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte {
   211  	sharedKey, err := curve25519.X25519(p.privateKey, peerPublicKey)
   212  	if err != nil {
   213  		return nil
   214  	}
   215  	return sharedKey
   216  }