Source file src/crypto/internal/fips140/aes/aes.go

     1  // Copyright 2009 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  package aes
     6  
     7  import (
     8  	"crypto/internal/fips140"
     9  	"crypto/internal/fips140/alias"
    10  	"strconv"
    11  )
    12  
    13  // BlockSize is the AES block size in bytes.
    14  const BlockSize = 16
    15  
    16  // A Block is an instance of AES using a particular key.
    17  // It is safe for concurrent use.
    18  type Block struct {
    19  	block
    20  }
    21  
    22  // blockExpanded is the block type used for all architectures except s390x,
    23  // which feeds the raw key directly to its instructions.
    24  type blockExpanded struct {
    25  	rounds int
    26  	// Round keys, where only the first (rounds + 1) × (128 ÷ 32) words are used.
    27  	enc [60]uint32
    28  	dec [60]uint32
    29  }
    30  
    31  const (
    32  	// AES-128 has 128-bit keys, 10 rounds, and uses 11 128-bit round keys
    33  	// (11×128÷32 = 44 32-bit words).
    34  
    35  	// AES-192 has 192-bit keys, 12 rounds, and uses 13 128-bit round keys
    36  	// (13×128÷32 = 52 32-bit words).
    37  
    38  	// AES-256 has 256-bit keys, 14 rounds, and uses 15 128-bit round keys
    39  	// (15×128÷32 = 60 32-bit words).
    40  
    41  	aes128KeySize = 16
    42  	aes192KeySize = 24
    43  	aes256KeySize = 32
    44  
    45  	aes128Rounds = 10
    46  	aes192Rounds = 12
    47  	aes256Rounds = 14
    48  )
    49  
    50  // roundKeysSize returns the number of uint32 of c.end or c.dec that are used.
    51  func (b *blockExpanded) roundKeysSize() int {
    52  	return (b.rounds + 1) * (128 / 32)
    53  }
    54  
    55  type KeySizeError int
    56  
    57  func (k KeySizeError) Error() string {
    58  	return "crypto/aes: invalid key size " + strconv.Itoa(int(k))
    59  }
    60  
    61  // New creates and returns a new [cipher.Block] implementation.
    62  // The key argument should be the AES key, either 16, 24, or 32 bytes to select
    63  // AES-128, AES-192, or AES-256.
    64  func New(key []byte) (*Block, error) {
    65  	// This call is outline to let the allocation happen on the parent stack.
    66  	return newOutlined(&Block{}, key)
    67  }
    68  
    69  // newOutlined is marked go:noinline to avoid it inlining into New, and making New
    70  // too complex to inline itself.
    71  //
    72  //go:noinline
    73  func newOutlined(b *Block, key []byte) (*Block, error) {
    74  	switch len(key) {
    75  	case aes128KeySize, aes192KeySize, aes256KeySize:
    76  	default:
    77  		return nil, KeySizeError(len(key))
    78  	}
    79  	return newBlock(b, key), nil
    80  }
    81  
    82  func newBlockExpanded(c *blockExpanded, key []byte) {
    83  	switch len(key) {
    84  	case aes128KeySize:
    85  		c.rounds = aes128Rounds
    86  	case aes192KeySize:
    87  		c.rounds = aes192Rounds
    88  	case aes256KeySize:
    89  		c.rounds = aes256Rounds
    90  	}
    91  	expandKeyGeneric(c, key)
    92  }
    93  
    94  func (c *Block) BlockSize() int { return BlockSize }
    95  
    96  func (c *Block) Encrypt(dst, src []byte) {
    97  	// AES-ECB is not approved in FIPS 140-3 mode.
    98  	fips140.RecordNonApproved()
    99  	if len(src) < BlockSize {
   100  		panic("crypto/aes: input not full block")
   101  	}
   102  	if len(dst) < BlockSize {
   103  		panic("crypto/aes: output not full block")
   104  	}
   105  	if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
   106  		panic("crypto/aes: invalid buffer overlap")
   107  	}
   108  	encryptBlock(c, dst, src)
   109  }
   110  
   111  func (c *Block) Decrypt(dst, src []byte) {
   112  	// AES-ECB is not approved in FIPS 140-3 mode.
   113  	fips140.RecordNonApproved()
   114  	if len(src) < BlockSize {
   115  		panic("crypto/aes: input not full block")
   116  	}
   117  	if len(dst) < BlockSize {
   118  		panic("crypto/aes: output not full block")
   119  	}
   120  	if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) {
   121  		panic("crypto/aes: invalid buffer overlap")
   122  	}
   123  	decryptBlock(c, dst, src)
   124  }
   125  
   126  // EncryptBlockInternal applies the AES encryption function to one block.
   127  //
   128  // It is an internal function meant only for the gcm package.
   129  func EncryptBlockInternal(c *Block, dst, src []byte) {
   130  	encryptBlock(c, dst, src)
   131  }
   132  

View as plain text