...

Source file src/crypto/aes/cipher_asm.go

Documentation: crypto/aes

		 1  // Copyright 2012 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  //go:build amd64 || arm64
		 6  // +build amd64 arm64
		 7  
		 8  package aes
		 9  
		10  import (
		11  	"crypto/cipher"
		12  	"crypto/internal/subtle"
		13  	"internal/cpu"
		14  )
		15  
		16  // defined in asm_*.s
		17  
		18  //go:noescape
		19  func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
		20  
		21  //go:noescape
		22  func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
		23  
		24  //go:noescape
		25  func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
		26  
		27  type aesCipherAsm struct {
		28  	aesCipher
		29  }
		30  
		31  var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasAES
		32  var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL
		33  
		34  func newCipher(key []byte) (cipher.Block, error) {
		35  	if !supportsAES {
		36  		return newCipherGeneric(key)
		37  	}
		38  	n := len(key) + 28
		39  	c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}}
		40  	var rounds int
		41  	switch len(key) {
		42  	case 128 / 8:
		43  		rounds = 10
		44  	case 192 / 8:
		45  		rounds = 12
		46  	case 256 / 8:
		47  		rounds = 14
		48  	}
		49  
		50  	expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0])
		51  	if supportsAES && supportsGFMUL {
		52  		return &aesCipherGCM{c}, nil
		53  	}
		54  	return &c, nil
		55  }
		56  
		57  func (c *aesCipherAsm) BlockSize() int { return BlockSize }
		58  
		59  func (c *aesCipherAsm) Encrypt(dst, src []byte) {
		60  	if len(src) < BlockSize {
		61  		panic("crypto/aes: input not full block")
		62  	}
		63  	if len(dst) < BlockSize {
		64  		panic("crypto/aes: output not full block")
		65  	}
		66  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
		67  		panic("crypto/aes: invalid buffer overlap")
		68  	}
		69  	encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0])
		70  }
		71  
		72  func (c *aesCipherAsm) Decrypt(dst, src []byte) {
		73  	if len(src) < BlockSize {
		74  		panic("crypto/aes: input not full block")
		75  	}
		76  	if len(dst) < BlockSize {
		77  		panic("crypto/aes: output not full block")
		78  	}
		79  	if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
		80  		panic("crypto/aes: invalid buffer overlap")
		81  	}
		82  	decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0])
		83  }
		84  
		85  // expandKey is used by BenchmarkExpand to ensure that the asm implementation
		86  // of key expansion is used for the benchmark when it is available.
		87  func expandKey(key []byte, enc, dec []uint32) {
		88  	if supportsAES {
		89  		rounds := 10 // rounds needed for AES128
		90  		switch len(key) {
		91  		case 192 / 8:
		92  			rounds = 12
		93  		case 256 / 8:
		94  			rounds = 14
		95  		}
		96  		expandKeyAsm(rounds, &key[0], &enc[0], &dec[0])
		97  	} else {
		98  		expandKeyGo(key, enc, dec)
		99  	}
	 100  }
	 101  

View as plain text