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)