...

Source file src/pkg/crypto/aes/cipher_asm.go

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

View as plain text