mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-10-19 07:55:07 +00:00
ad0f7a5305
Upgrade to Go 1.20.5, Hydra v2 SDK, rules-go v0.44.2 (with proper resolves), protobuf v25.3 and mass upgrade of Go dependencies.
132 lines
4.0 KiB
Go
132 lines
4.0 KiB
Go
/*
|
|
*
|
|
* Copyright 2018 gRPC authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
package conn
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
// rekeyAEAD holds the necessary information for an AEAD based on
|
|
// AES-GCM that performs nonce-based key derivation and XORs the
|
|
// nonce with a random mask.
|
|
type rekeyAEAD struct {
|
|
kdfKey []byte
|
|
kdfCounter []byte
|
|
nonceMask []byte
|
|
nonceBuf []byte
|
|
gcmAEAD cipher.AEAD
|
|
}
|
|
|
|
// KeySizeError signals that the given key does not have the correct size.
|
|
type KeySizeError int
|
|
|
|
func (k KeySizeError) Error() string {
|
|
return "alts/conn: invalid key size " + strconv.Itoa(int(k))
|
|
}
|
|
|
|
// newRekeyAEAD creates a new instance of aes128gcm with rekeying.
|
|
// The key argument should be 44 bytes, the first 32 bytes are used as a key
|
|
// for HKDF-expand and the remainining 12 bytes are used as a random mask for
|
|
// the counter.
|
|
func newRekeyAEAD(key []byte) (*rekeyAEAD, error) {
|
|
k := len(key)
|
|
if k != kdfKeyLen+nonceLen {
|
|
return nil, KeySizeError(k)
|
|
}
|
|
return &rekeyAEAD{
|
|
kdfKey: key[:kdfKeyLen],
|
|
kdfCounter: make([]byte, kdfCounterLen),
|
|
nonceMask: key[kdfKeyLen:],
|
|
nonceBuf: make([]byte, nonceLen),
|
|
gcmAEAD: nil,
|
|
}, nil
|
|
}
|
|
|
|
// Seal rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
|
// and calls Seal for aes128gcm.
|
|
func (s *rekeyAEAD) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
|
|
if err := s.rekeyIfRequired(nonce); err != nil {
|
|
panic(fmt.Sprintf("Rekeying failed with: %s", err.Error()))
|
|
}
|
|
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
|
return s.gcmAEAD.Seal(dst, s.nonceBuf, plaintext, additionalData)
|
|
}
|
|
|
|
// Open rekeys if nonce[2:8] is different than in the last call, masks the nonce,
|
|
// and calls Open for aes128gcm.
|
|
func (s *rekeyAEAD) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
|
if err := s.rekeyIfRequired(nonce); err != nil {
|
|
return nil, err
|
|
}
|
|
maskNonce(s.nonceBuf, nonce, s.nonceMask)
|
|
return s.gcmAEAD.Open(dst, s.nonceBuf, ciphertext, additionalData)
|
|
}
|
|
|
|
// rekeyIfRequired creates a new aes128gcm AEAD if the existing AEAD is nil
|
|
// or cannot be used with given nonce.
|
|
func (s *rekeyAEAD) rekeyIfRequired(nonce []byte) error {
|
|
newKdfCounter := nonce[kdfCounterOffset : kdfCounterOffset+kdfCounterLen]
|
|
if s.gcmAEAD != nil && bytes.Equal(newKdfCounter, s.kdfCounter) {
|
|
return nil
|
|
}
|
|
copy(s.kdfCounter, newKdfCounter)
|
|
a, err := aes.NewCipher(hkdfExpand(s.kdfKey, s.kdfCounter))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.gcmAEAD, err = cipher.NewGCM(a)
|
|
return err
|
|
}
|
|
|
|
// maskNonce XORs the given nonce with the mask and stores the result in dst.
|
|
func maskNonce(dst, nonce, mask []byte) {
|
|
nonce1 := binary.LittleEndian.Uint64(nonce[:sizeUint64])
|
|
nonce2 := binary.LittleEndian.Uint32(nonce[sizeUint64:])
|
|
mask1 := binary.LittleEndian.Uint64(mask[:sizeUint64])
|
|
mask2 := binary.LittleEndian.Uint32(mask[sizeUint64:])
|
|
binary.LittleEndian.PutUint64(dst[:sizeUint64], nonce1^mask1)
|
|
binary.LittleEndian.PutUint32(dst[sizeUint64:], nonce2^mask2)
|
|
}
|
|
|
|
// NonceSize returns the required nonce size.
|
|
func (s *rekeyAEAD) NonceSize() int {
|
|
return s.gcmAEAD.NonceSize()
|
|
}
|
|
|
|
// Overhead returns the ciphertext overhead.
|
|
func (s *rekeyAEAD) Overhead() int {
|
|
return s.gcmAEAD.Overhead()
|
|
}
|
|
|
|
// hkdfExpand computes the first 16 bytes of the HKDF-expand function
|
|
// defined in RFC5869.
|
|
func hkdfExpand(key, info []byte) []byte {
|
|
mac := hmac.New(sha256.New, key)
|
|
mac.Write(info)
|
|
mac.Write([]byte{0x01}[:])
|
|
return mac.Sum(nil)[:aeadKeyLen]
|
|
}
|