mirror of
https://github.com/XTLS/REALITY.git
synced 2025-08-22 14:38:35 +00:00
131 lines
3.4 KiB
Go
131 lines
3.4 KiB
Go
// Copyright 2009 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.
|
||
|
||
package aes
|
||
|
||
import (
|
||
"strconv"
|
||
|
||
"github.com/xtls/reality/alias"
|
||
)
|
||
|
||
// BlockSize is the AES block size in bytes.
|
||
const BlockSize = 16
|
||
|
||
// A Block is an instance of AES using a particular key.
|
||
// It is safe for concurrent use.
|
||
type Block struct {
|
||
block
|
||
}
|
||
|
||
// blockExpanded is the block type used for all architectures except s390x,
|
||
// which feeds the raw key directly to its instructions.
|
||
type blockExpanded struct {
|
||
rounds int
|
||
// Round keys, where only the first (rounds + 1) × (128 ÷ 32) words are used.
|
||
enc [60]uint32
|
||
dec [60]uint32
|
||
}
|
||
|
||
const (
|
||
// AES-128 has 128-bit keys, 10 rounds, and uses 11 128-bit round keys
|
||
// (11×128÷32 = 44 32-bit words).
|
||
|
||
// AES-192 has 192-bit keys, 12 rounds, and uses 13 128-bit round keys
|
||
// (13×128÷32 = 52 32-bit words).
|
||
|
||
// AES-256 has 256-bit keys, 14 rounds, and uses 15 128-bit round keys
|
||
// (15×128÷32 = 60 32-bit words).
|
||
|
||
aes128KeySize = 16
|
||
aes192KeySize = 24
|
||
aes256KeySize = 32
|
||
|
||
aes128Rounds = 10
|
||
aes192Rounds = 12
|
||
aes256Rounds = 14
|
||
)
|
||
|
||
// roundKeysSize returns the number of uint32 of c.end or c.dec that are used.
|
||
func (b *blockExpanded) roundKeysSize() int {
|
||
return (b.rounds + 1) * (128 / 32)
|
||
}
|
||
|
||
type KeySizeError int
|
||
|
||
func (k KeySizeError) Error() string {
|
||
return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
|
||
}
|
||
|
||
// New creates and returns a new [cipher.Block] implementation.
|
||
// The key argument should be the AES key, either 16, 24, or 32 bytes to select
|
||
// AES-128, AES-192, or AES-256.
|
||
func New(key []byte) (*Block, error) {
|
||
// This call is outline to let the allocation happen on the parent stack.
|
||
return newOutlined(&Block{}, key)
|
||
}
|
||
|
||
// newOutlined is marked go:noinline to avoid it inlining into New, and making New
|
||
// too complex to inline itself.
|
||
//
|
||
//go:noinline
|
||
func newOutlined(b *Block, key []byte) (*Block, error) {
|
||
switch len(key) {
|
||
case aes128KeySize, aes192KeySize, aes256KeySize:
|
||
default:
|
||
return nil, KeySizeError(len(key))
|
||
}
|
||
return newBlock(b, key), nil
|
||
}
|
||
|
||
func newBlockExpanded(c *blockExpanded, key []byte) {
|
||
switch len(key) {
|
||
case aes128KeySize:
|
||
c.rounds = aes128Rounds
|
||
case aes192KeySize:
|
||
c.rounds = aes192Rounds
|
||
case aes256KeySize:
|
||
c.rounds = aes256Rounds
|
||
}
|
||
expandKeyGeneric(c, key)
|
||
}
|
||
|
||
func (c *Block) BlockSize() int { return BlockSize }
|
||
|
||
func (c *Block) Encrypt(dst, src []byte) {
|
||
// AES-ECB is not approved in FIPS 140-3 mode.
|
||
// fips140.RecordNonApproved()
|
||
if len(src) < BlockSize {
|
||
panic("crypto/aes: input not full block")
|
||
}
|
||
if len(dst) < BlockSize {
|
||
panic("crypto/aes: output not full block")
|
||
}
|
||
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||
panic("crypto/aes: invalid buffer overlap")
|
||
}
|
||
encryptBlock(c, dst, src)
|
||
}
|
||
|
||
func (c *Block) Decrypt(dst, src []byte) {
|
||
// AES-ECB is not approved in FIPS 140-3 mode.
|
||
// fips140.RecordNonApproved()
|
||
if len(src) < BlockSize {
|
||
panic("crypto/aes: input not full block")
|
||
}
|
||
if len(dst) < BlockSize {
|
||
panic("crypto/aes: output not full block")
|
||
}
|
||
if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
|
||
panic("crypto/aes: invalid buffer overlap")
|
||
}
|
||
decryptBlock(c, dst, src)
|
||
}
|
||
|
||
// EncryptBlockInternal applies the AES encryption function to one block.
|
||
//
|
||
// It is an internal function meant only for the gcm package.
|
||
func EncryptBlockInternal(c *Block, dst, src []byte) {
|
||
encryptBlock(c, dst, src)
|
||
} |