github.com/birneee/aes6@v0.0.0-20240131140838-9e8f775f7eae/gcm.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package aes6 6 7 import ( 8 "crypto/cipher" 9 "errors" 10 "fmt" 11 "reflect" 12 "unsafe" 13 ) 14 15 // copy of crypto/cipher 16 type gcmAble interface { 17 NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) 18 } 19 20 // copy of crypto/cipher with reduced minimum tagSize 21 func NewGCMWithTagSize(cipher cipher.Block, tagSize int) (cipher.AEAD, error) { 22 return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize) 23 } 24 25 // inspired by crypto/cipher with reduced minimum tagSize 26 func newGCMWithNonceAndTagSize(cipher cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) { 27 if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { 28 return nil, errors.New("cipher: incorrect tag size given to GCM") 29 } 30 31 if nonceSize <= 0 { 32 return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised") 33 } 34 35 if cipher, ok := cipher.(gcmAble); ok { 36 cipherType := reflect.TypeOf(cipher) 37 switch cipherType.String() { 38 case "*aes.aesCipherGCM": 39 // a := (*aesCipherGCM)(unsafe.Pointer(reflect.ValueOf(cipher).Pointer())) // alternative 40 a := (*((*[2]*aesCipherGCM)(unsafe.Pointer(&cipher))))[1] // this is a bit hacky 41 return a.NewGCM(nonceSize, tagSize) 42 case "*aes8.aesCipherGCM": 43 return cipher.NewGCM(nonceSize, tagSize) 44 default: 45 return nil, fmt.Errorf("type not supported: %s", cipherType) 46 } 47 } else { 48 return nil, fmt.Errorf("type is not gcmAble") 49 } 50 } 51 52 //go:linkname errOpen crypto/cipher.errOpen 53 var errOpen error 54 55 //go:linkname sliceForAppend crypto/cipher.sliceForAppend 56 func sliceForAppend(in []byte, n int) (head, tail []byte)