github.com/tailscale/wireguard-go@v0.0.20201119-0.20210522003738-46b531feb08a/device/noise-helpers.go (about)

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