github.com/noisysockets/noisysockets@v0.21.2-0.20240515114641-7f467e651c90/internal/transport/noise_helpers.go (about) 1 // SPDX-License-Identifier: MPL-2.0 2 /* 3 * Copyright (C) 2024 The Noisy Sockets Authors. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * Portions of this file are based on code originally from wireguard-go, 10 * 11 * Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved. 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy of 14 * this software and associated documentation files (the "Software"), to deal in 15 * the Software without restriction, including without limitation the rights to 16 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 17 * of the Software, and to permit persons to whom the Software is furnished to do 18 * so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in all 21 * copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 * SOFTWARE. 30 */ 31 32 package transport 33 34 import ( 35 "crypto/hmac" 36 "crypto/subtle" 37 "errors" 38 "hash" 39 40 "github.com/noisysockets/noisysockets/types" 41 "golang.org/x/crypto/blake2s" 42 "golang.org/x/crypto/curve25519" 43 ) 44 45 /* KDF related functions. 46 * HMAC-based Key Derivation Function (HKDF) 47 * https://tools.ietf.org/html/rfc5869 48 */ 49 50 func HMAC1(sum *[blake2s.Size]byte, key, in0 []byte) { 51 mac := hmac.New(func() hash.Hash { 52 h, _ := blake2s.New256(nil) 53 return h 54 }, key) 55 mac.Write(in0) 56 mac.Sum(sum[:0]) 57 } 58 59 func HMAC2(sum *[blake2s.Size]byte, key, in0, in1 []byte) { 60 mac := hmac.New(func() hash.Hash { 61 h, _ := blake2s.New256(nil) 62 return h 63 }, key) 64 mac.Write(in0) 65 mac.Write(in1) 66 mac.Sum(sum[:0]) 67 } 68 69 func KDF1(t0 *[blake2s.Size]byte, key, input []byte) { 70 HMAC1(t0, key, input) 71 HMAC1(t0, t0[:], []byte{0x1}) 72 } 73 74 func KDF2(t0, t1 *[blake2s.Size]byte, key, input []byte) { 75 var prk [blake2s.Size]byte 76 HMAC1(&prk, key, input) 77 HMAC1(t0, prk[:], []byte{0x1}) 78 HMAC2(t1, prk[:], t0[:], []byte{0x2}) 79 setZero(prk[:]) 80 } 81 82 func KDF3(t0, t1, t2 *[blake2s.Size]byte, key, input []byte) { 83 var prk [blake2s.Size]byte 84 HMAC1(&prk, key, input) 85 HMAC1(t0, prk[:], []byte{0x1}) 86 HMAC2(t1, prk[:], t0[:], []byte{0x2}) 87 HMAC2(t2, prk[:], t1[:], []byte{0x3}) 88 setZero(prk[:]) 89 } 90 91 func isZero(val []byte) bool { 92 acc := 1 93 for _, b := range val { 94 acc &= subtle.ConstantTimeByteEq(b, 0) 95 } 96 return acc == 1 97 } 98 99 /* This function is not used as pervasively as it should because this is mostly impossible in Go at the moment */ 100 func setZero(arr []byte) { 101 for i := range arr { 102 arr[i] = 0 103 } 104 } 105 106 var errInvalidPublicKey = errors.New("invalid public key") 107 108 func sharedSecret(sk types.NoisePrivateKey, pk types.NoisePublicKey) (ss [types.NoisePublicKeySize]byte, err error) { 109 apk := (*[types.NoisePublicKeySize]byte)(&pk) 110 ask := (*[types.NoisePrivateKeySize]byte)(&sk) 111 result, err := curve25519.X25519(ask[:], apk[:]) 112 if err != nil || isZero(result) { 113 return ss, errInvalidPublicKey 114 } 115 copy(ss[:], result) 116 return ss, nil 117 }