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 }