// 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 ( "crypto/internal/fips140" "crypto/internal/fips140/alias" "strconv" ) // 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) }