github.com/koomox/wireguard-go@v0.0.0-20230722134753-17a50b2f22a3/device/noise-helpers.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2023 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 }