gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/credentials/alts/internal/conn/aes128gcmrekey.go (about) 1 /* 2 * 3 * Copyright 2018 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package conn 20 21 import ( 22 "crypto/cipher" 23 24 core "gitee.com/ks-custle/core-gm/grpc/credentials/alts/internal" 25 ) 26 27 const ( 28 // Overflow length n in bytes, never encrypt more than 2^(n*8) frames (in 29 // each direction). 30 overflowLenAES128GCMRekey = 8 31 nonceLen = 12 32 aeadKeyLen = 16 33 kdfKeyLen = 32 34 kdfCounterOffset = 2 35 kdfCounterLen = 6 36 sizeUint64 = 8 37 ) 38 39 // aes128gcmRekey is the struct that holds necessary information for ALTS record. 40 // The counter value is NOT included in the payload during the encryption and 41 // decryption operations. 42 type aes128gcmRekey struct { 43 // inCounter is used in ALTS record to check that incoming counters are 44 // as expected, since ALTS record guarantees that messages are unwrapped 45 // in the same order that the peer wrapped them. 46 inCounter Counter 47 outCounter Counter 48 inAEAD cipher.AEAD 49 outAEAD cipher.AEAD 50 } 51 52 // NewAES128GCMRekey creates an instance that uses aes128gcm with rekeying 53 // for ALTS record. The key argument should be 44 bytes, the first 32 bytes 54 // are used as a key for HKDF-expand and the remainining 12 bytes are used 55 // as a random mask for the counter. 56 func NewAES128GCMRekey(side core.Side, key []byte) (ALTSRecordCrypto, error) { 57 inCounter := NewInCounter(side, overflowLenAES128GCMRekey) 58 outCounter := NewOutCounter(side, overflowLenAES128GCMRekey) 59 inAEAD, err := newRekeyAEAD(key) 60 if err != nil { 61 return nil, err 62 } 63 outAEAD, err := newRekeyAEAD(key) 64 if err != nil { 65 return nil, err 66 } 67 return &aes128gcmRekey{ 68 inCounter, 69 outCounter, 70 inAEAD, 71 outAEAD, 72 }, nil 73 } 74 75 // Encrypt is the encryption function. dst can contain bytes at the beginning of 76 // the ciphertext that will not be encrypted but will be authenticated. If dst 77 // has enough capacity to hold these bytes, the ciphertext and the tag, no 78 // allocation and copy operations will be performed. dst and plaintext do not 79 // overlap. 80 func (s *aes128gcmRekey) Encrypt(dst, plaintext []byte) ([]byte, error) { 81 // If we need to allocate an output buffer, we want to include space for 82 // GCM tag to avoid forcing ALTS record to reallocate as well. 83 dlen := len(dst) 84 dst, out := SliceForAppend(dst, len(plaintext)+GcmTagSize) 85 seq, err := s.outCounter.Value() 86 if err != nil { 87 return nil, err 88 } 89 data := out[:len(plaintext)] 90 copy(data, plaintext) // data may alias plaintext 91 92 // Seal appends the ciphertext and the tag to its first argument and 93 // returns the updated slice. However, SliceForAppend above ensures that 94 // dst has enough capacity to avoid a reallocation and copy due to the 95 // append. 96 dst = s.outAEAD.Seal(dst[:dlen], seq, data, nil) 97 s.outCounter.Inc() 98 return dst, nil 99 } 100 101 func (s *aes128gcmRekey) EncryptionOverhead() int { 102 return GcmTagSize 103 } 104 105 func (s *aes128gcmRekey) Decrypt(dst, ciphertext []byte) ([]byte, error) { 106 seq, err := s.inCounter.Value() 107 if err != nil { 108 return nil, err 109 } 110 plaintext, err := s.inAEAD.Open(dst, seq, ciphertext, nil) 111 if err != nil { 112 return nil, ErrAuth 113 } 114 s.inCounter.Inc() 115 return plaintext, nil 116 }