mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	The vendor/ folder was created with the help of @FiloSottile's gvt and vendorcheck. Any dependencies of Caddy plugins outside this repo are not vendored. We do not remove any unused, vendored packages because vendorcheck -u only checks using the current build configuration; i.e. packages that may be imported by files toggled by build tags of other systems. CI tests have been updated to ignore the vendor/ folder. When Go 1.9 is released, a few of the go commands should be revised to again use ./... as it will ignore the vendor folder by default.
		
			
				
	
	
		
			149 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2015 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
// +build amd64
 | 
						|
 | 
						|
package aes12
 | 
						|
 | 
						|
import "crypto/subtle"
 | 
						|
 | 
						|
// The following functions are defined in gcm_amd64.s.
 | 
						|
func hasGCMAsm() bool
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func aesEncBlock(dst, src *[16]byte, ks []uint32)
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func gcmAesInit(productTable *[256]byte, ks []uint32)
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte)
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
 | 
						|
 | 
						|
//go:noescape
 | 
						|
func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64)
 | 
						|
 | 
						|
// aesCipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM
 | 
						|
// will use the optimised implementation in this file when possible. Instances
 | 
						|
// of this type only exist when hasGCMAsm returns true.
 | 
						|
type aesCipherGCM struct {
 | 
						|
	aesCipherAsm
 | 
						|
}
 | 
						|
 | 
						|
// Assert that aesCipherGCM implements the gcmAble interface.
 | 
						|
var _ gcmAble = (*aesCipherGCM)(nil)
 | 
						|
 | 
						|
// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
 | 
						|
// called by crypto/cipher.NewGCM via the gcmAble interface.
 | 
						|
func (c *aesCipherGCM) NewGCM(nonceSize int) (AEAD, error) {
 | 
						|
	g := &gcmAsm{ks: c.enc, nonceSize: nonceSize}
 | 
						|
	gcmAesInit(&g.productTable, g.ks)
 | 
						|
	return g, nil
 | 
						|
}
 | 
						|
 | 
						|
type gcmAsm struct {
 | 
						|
	// ks is the key schedule, the length of which depends on the size of
 | 
						|
	// the AES key.
 | 
						|
	ks []uint32
 | 
						|
	// productTable contains pre-computed multiples of the binary-field
 | 
						|
	// element used in GHASH.
 | 
						|
	productTable [256]byte
 | 
						|
	// nonceSize contains the expected size of the nonce, in bytes.
 | 
						|
	nonceSize int
 | 
						|
}
 | 
						|
 | 
						|
func (g *gcmAsm) NonceSize() int {
 | 
						|
	return g.nonceSize
 | 
						|
}
 | 
						|
 | 
						|
func (*gcmAsm) Overhead() int {
 | 
						|
	return gcmTagSize
 | 
						|
}
 | 
						|
 | 
						|
// Seal encrypts and authenticates plaintext. See the AEAD interface for
 | 
						|
// details.
 | 
						|
func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
 | 
						|
	if len(nonce) != g.nonceSize {
 | 
						|
		panic("cipher: incorrect nonce length given to GCM")
 | 
						|
	}
 | 
						|
 | 
						|
	var counter, tagMask [gcmBlockSize]byte
 | 
						|
 | 
						|
	if len(nonce) == gcmStandardNonceSize {
 | 
						|
		// Init counter to nonce||1
 | 
						|
		copy(counter[:], nonce)
 | 
						|
		counter[gcmBlockSize-1] = 1
 | 
						|
	} else {
 | 
						|
		// Otherwise counter = GHASH(nonce)
 | 
						|
		gcmAesData(&g.productTable, nonce, &counter)
 | 
						|
		gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0))
 | 
						|
	}
 | 
						|
 | 
						|
	aesEncBlock(&tagMask, &counter, g.ks)
 | 
						|
 | 
						|
	var tagOut [16]byte
 | 
						|
	gcmAesData(&g.productTable, data, &tagOut)
 | 
						|
 | 
						|
	ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
 | 
						|
	if len(plaintext) > 0 {
 | 
						|
		gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks)
 | 
						|
	}
 | 
						|
	gcmAesFinish(&g.productTable, &tagMask, &tagOut, uint64(len(plaintext)), uint64(len(data)))
 | 
						|
	copy(out[len(plaintext):], tagOut[:gcmTagSize])
 | 
						|
 | 
						|
	return ret
 | 
						|
}
 | 
						|
 | 
						|
// Open authenticates and decrypts ciphertext. See the AEAD interface
 | 
						|
// for details.
 | 
						|
func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 | 
						|
	if len(nonce) != g.nonceSize {
 | 
						|
		panic("cipher: incorrect nonce length given to GCM")
 | 
						|
	}
 | 
						|
 | 
						|
	if len(ciphertext) < gcmTagSize {
 | 
						|
		return nil, errOpen
 | 
						|
	}
 | 
						|
	tag := ciphertext[len(ciphertext)-gcmTagSize:]
 | 
						|
	ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
 | 
						|
 | 
						|
	// See GCM spec, section 7.1.
 | 
						|
	var counter, tagMask [gcmBlockSize]byte
 | 
						|
 | 
						|
	if len(nonce) == gcmStandardNonceSize {
 | 
						|
		// Init counter to nonce||1
 | 
						|
		copy(counter[:], nonce)
 | 
						|
		counter[gcmBlockSize-1] = 1
 | 
						|
	} else {
 | 
						|
		// Otherwise counter = GHASH(nonce)
 | 
						|
		gcmAesData(&g.productTable, nonce, &counter)
 | 
						|
		gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0))
 | 
						|
	}
 | 
						|
 | 
						|
	aesEncBlock(&tagMask, &counter, g.ks)
 | 
						|
 | 
						|
	var expectedTag [16]byte
 | 
						|
	gcmAesData(&g.productTable, data, &expectedTag)
 | 
						|
 | 
						|
	ret, out := sliceForAppend(dst, len(ciphertext))
 | 
						|
	if len(ciphertext) > 0 {
 | 
						|
		gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks)
 | 
						|
	}
 | 
						|
	gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
 | 
						|
 | 
						|
	if subtle.ConstantTimeCompare(expectedTag[:12], tag) != 1 {
 | 
						|
		for i := range out {
 | 
						|
			out[i] = 0
 | 
						|
		}
 | 
						|
		return nil, errOpen
 | 
						|
	}
 | 
						|
 | 
						|
	return ret, nil
 | 
						|
}
 |