noise-helpers.go raw

   1  /* SPDX-License-Identifier: MIT
   2   *
   3   * Copyright (C) 2017-2025 WireGuard LLC. All Rights Reserved.
   4   */
   5  
   6  package device
   7  
   8  import (
   9  	"crypto/hmac"
  10  	"crypto/rand"
  11  	"crypto/subtle"
  12  	"errors"
  13  	"hash"
  14  
  15  	"golang.org/x/crypto/blake2s"
  16  	"golang.org/x/crypto/curve25519"
  17  )
  18  
  19  /* KDF related functions.
  20   * HMAC-based Key Derivation Function (HKDF)
  21   * https://tools.ietf.org/html/rfc5869
  22   */
  23  
  24  func HMAC1(sum *[blake2s.Size]byte, key, in0 []byte) {
  25  	mac := hmac.New(func() hash.Hash {
  26  		h, _ := blake2s.New256(nil)
  27  		return h
  28  	}, key)
  29  	mac.Write(in0)
  30  	mac.Sum(sum[:0])
  31  }
  32  
  33  func HMAC2(sum *[blake2s.Size]byte, key, in0, in1 []byte) {
  34  	mac := hmac.New(func() hash.Hash {
  35  		h, _ := blake2s.New256(nil)
  36  		return h
  37  	}, key)
  38  	mac.Write(in0)
  39  	mac.Write(in1)
  40  	mac.Sum(sum[:0])
  41  }
  42  
  43  func KDF1(t0 *[blake2s.Size]byte, key, input []byte) {
  44  	HMAC1(t0, key, input)
  45  	HMAC1(t0, t0[:], []byte{0x1})
  46  }
  47  
  48  func KDF2(t0, t1 *[blake2s.Size]byte, key, input []byte) {
  49  	var prk [blake2s.Size]byte
  50  	HMAC1(&prk, key, input)
  51  	HMAC1(t0, prk[:], []byte{0x1})
  52  	HMAC2(t1, prk[:], t0[:], []byte{0x2})
  53  	setZero(prk[:])
  54  }
  55  
  56  func KDF3(t0, t1, t2 *[blake2s.Size]byte, key, input []byte) {
  57  	var prk [blake2s.Size]byte
  58  	HMAC1(&prk, key, input)
  59  	HMAC1(t0, prk[:], []byte{0x1})
  60  	HMAC2(t1, prk[:], t0[:], []byte{0x2})
  61  	HMAC2(t2, prk[:], t1[:], []byte{0x3})
  62  	setZero(prk[:])
  63  }
  64  
  65  func isZero(val []byte) bool {
  66  	acc := 1
  67  	for _, b := range val {
  68  		acc &= subtle.ConstantTimeByteEq(b, 0)
  69  	}
  70  	return acc == 1
  71  }
  72  
  73  /* This function is not used as pervasively as it should because this is mostly impossible in Go at the moment */
  74  func setZero(arr []byte) {
  75  	for i := range arr {
  76  		arr[i] = 0
  77  	}
  78  }
  79  
  80  func (sk *NoisePrivateKey) clamp() {
  81  	sk[0] &= 248
  82  	sk[31] = (sk[31] & 127) | 64
  83  }
  84  
  85  func newPrivateKey() (sk NoisePrivateKey, err error) {
  86  	_, err = rand.Read(sk[:])
  87  	sk.clamp()
  88  	return
  89  }
  90  
  91  func (sk *NoisePrivateKey) publicKey() (pk NoisePublicKey) {
  92  	apk := (*[NoisePublicKeySize]byte)(&pk)
  93  	ask := (*[NoisePrivateKeySize]byte)(sk)
  94  	curve25519.ScalarBaseMult(apk, ask)
  95  	return
  96  }
  97  
  98  var errInvalidPublicKey = errors.New("invalid public key")
  99  
 100  func (sk *NoisePrivateKey) sharedSecret(pk NoisePublicKey) (ss [NoisePublicKeySize]byte, err error) {
 101  	apk := (*[NoisePublicKeySize]byte)(&pk)
 102  	ask := (*[NoisePrivateKeySize]byte)(sk)
 103  	curve25519.ScalarMult(&ss, ask, apk)
 104  	if isZero(ss[:]) {
 105  		return ss, errInvalidPublicKey
 106  	}
 107  	return ss, nil
 108  }
 109