...

Source file src/crypto/aes/block.go

Documentation: crypto/aes

		 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  // This Go implementation is derived in part from the reference
		 6  // ANSI C implementation, which carries the following notice:
		 7  //
		 8  //	rijndael-alg-fst.c
		 9  //
		10  //	@version 3.0 (December 2000)
		11  //
		12  //	Optimised ANSI C code for the Rijndael cipher (now AES)
		13  //
		14  //	@author Vincent Rijmen <[email protected]>
		15  //	@author Antoon Bosselaers <[email protected]>
		16  //	@author Paulo Barreto <[email protected]>
		17  //
		18  //	This code is hereby placed in the public domain.
		19  //
		20  //	THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
		21  //	OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
		22  //	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
		23  //	ARE DISCLAIMED.	IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
		24  //	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
		25  //	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
		26  //	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
		27  //	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
		28  //	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
		29  //	OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
		30  //	EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
		31  //
		32  // See FIPS 197 for specification, and see Daemen and Rijmen's Rijndael submission
		33  // for implementation details.
		34  //	https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf
		35  //	https://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf
		36  
		37  package aes
		38  
		39  import (
		40  	"encoding/binary"
		41  )
		42  
		43  // Encrypt one block from src into dst, using the expanded key xk.
		44  func encryptBlockGo(xk []uint32, dst, src []byte) {
		45  	_ = src[15] // early bounds check
		46  	s0 := binary.BigEndian.Uint32(src[0:4])
		47  	s1 := binary.BigEndian.Uint32(src[4:8])
		48  	s2 := binary.BigEndian.Uint32(src[8:12])
		49  	s3 := binary.BigEndian.Uint32(src[12:16])
		50  
		51  	// First round just XORs input with key.
		52  	s0 ^= xk[0]
		53  	s1 ^= xk[1]
		54  	s2 ^= xk[2]
		55  	s3 ^= xk[3]
		56  
		57  	// Middle rounds shuffle using tables.
		58  	// Number of rounds is set by length of expanded key.
		59  	nr := len(xk)/4 - 2 // - 2: one above, one more below
		60  	k := 4
		61  	var t0, t1, t2, t3 uint32
		62  	for r := 0; r < nr; r++ {
		63  		t0 = xk[k+0] ^ te0[uint8(s0>>24)] ^ te1[uint8(s1>>16)] ^ te2[uint8(s2>>8)] ^ te3[uint8(s3)]
		64  		t1 = xk[k+1] ^ te0[uint8(s1>>24)] ^ te1[uint8(s2>>16)] ^ te2[uint8(s3>>8)] ^ te3[uint8(s0)]
		65  		t2 = xk[k+2] ^ te0[uint8(s2>>24)] ^ te1[uint8(s3>>16)] ^ te2[uint8(s0>>8)] ^ te3[uint8(s1)]
		66  		t3 = xk[k+3] ^ te0[uint8(s3>>24)] ^ te1[uint8(s0>>16)] ^ te2[uint8(s1>>8)] ^ te3[uint8(s2)]
		67  		k += 4
		68  		s0, s1, s2, s3 = t0, t1, t2, t3
		69  	}
		70  
		71  	// Last round uses s-box directly and XORs to produce output.
		72  	s0 = uint32(sbox0[t0>>24])<<24 | uint32(sbox0[t1>>16&0xff])<<16 | uint32(sbox0[t2>>8&0xff])<<8 | uint32(sbox0[t3&0xff])
		73  	s1 = uint32(sbox0[t1>>24])<<24 | uint32(sbox0[t2>>16&0xff])<<16 | uint32(sbox0[t3>>8&0xff])<<8 | uint32(sbox0[t0&0xff])
		74  	s2 = uint32(sbox0[t2>>24])<<24 | uint32(sbox0[t3>>16&0xff])<<16 | uint32(sbox0[t0>>8&0xff])<<8 | uint32(sbox0[t1&0xff])
		75  	s3 = uint32(sbox0[t3>>24])<<24 | uint32(sbox0[t0>>16&0xff])<<16 | uint32(sbox0[t1>>8&0xff])<<8 | uint32(sbox0[t2&0xff])
		76  
		77  	s0 ^= xk[k+0]
		78  	s1 ^= xk[k+1]
		79  	s2 ^= xk[k+2]
		80  	s3 ^= xk[k+3]
		81  
		82  	_ = dst[15] // early bounds check
		83  	binary.BigEndian.PutUint32(dst[0:4], s0)
		84  	binary.BigEndian.PutUint32(dst[4:8], s1)
		85  	binary.BigEndian.PutUint32(dst[8:12], s2)
		86  	binary.BigEndian.PutUint32(dst[12:16], s3)
		87  }
		88  
		89  // Decrypt one block from src into dst, using the expanded key xk.
		90  func decryptBlockGo(xk []uint32, dst, src []byte) {
		91  	_ = src[15] // early bounds check
		92  	s0 := binary.BigEndian.Uint32(src[0:4])
		93  	s1 := binary.BigEndian.Uint32(src[4:8])
		94  	s2 := binary.BigEndian.Uint32(src[8:12])
		95  	s3 := binary.BigEndian.Uint32(src[12:16])
		96  
		97  	// First round just XORs input with key.
		98  	s0 ^= xk[0]
		99  	s1 ^= xk[1]
	 100  	s2 ^= xk[2]
	 101  	s3 ^= xk[3]
	 102  
	 103  	// Middle rounds shuffle using tables.
	 104  	// Number of rounds is set by length of expanded key.
	 105  	nr := len(xk)/4 - 2 // - 2: one above, one more below
	 106  	k := 4
	 107  	var t0, t1, t2, t3 uint32
	 108  	for r := 0; r < nr; r++ {
	 109  		t0 = xk[k+0] ^ td0[uint8(s0>>24)] ^ td1[uint8(s3>>16)] ^ td2[uint8(s2>>8)] ^ td3[uint8(s1)]
	 110  		t1 = xk[k+1] ^ td0[uint8(s1>>24)] ^ td1[uint8(s0>>16)] ^ td2[uint8(s3>>8)] ^ td3[uint8(s2)]
	 111  		t2 = xk[k+2] ^ td0[uint8(s2>>24)] ^ td1[uint8(s1>>16)] ^ td2[uint8(s0>>8)] ^ td3[uint8(s3)]
	 112  		t3 = xk[k+3] ^ td0[uint8(s3>>24)] ^ td1[uint8(s2>>16)] ^ td2[uint8(s1>>8)] ^ td3[uint8(s0)]
	 113  		k += 4
	 114  		s0, s1, s2, s3 = t0, t1, t2, t3
	 115  	}
	 116  
	 117  	// Last round uses s-box directly and XORs to produce output.
	 118  	s0 = uint32(sbox1[t0>>24])<<24 | uint32(sbox1[t3>>16&0xff])<<16 | uint32(sbox1[t2>>8&0xff])<<8 | uint32(sbox1[t1&0xff])
	 119  	s1 = uint32(sbox1[t1>>24])<<24 | uint32(sbox1[t0>>16&0xff])<<16 | uint32(sbox1[t3>>8&0xff])<<8 | uint32(sbox1[t2&0xff])
	 120  	s2 = uint32(sbox1[t2>>24])<<24 | uint32(sbox1[t1>>16&0xff])<<16 | uint32(sbox1[t0>>8&0xff])<<8 | uint32(sbox1[t3&0xff])
	 121  	s3 = uint32(sbox1[t3>>24])<<24 | uint32(sbox1[t2>>16&0xff])<<16 | uint32(sbox1[t1>>8&0xff])<<8 | uint32(sbox1[t0&0xff])
	 122  
	 123  	s0 ^= xk[k+0]
	 124  	s1 ^= xk[k+1]
	 125  	s2 ^= xk[k+2]
	 126  	s3 ^= xk[k+3]
	 127  
	 128  	_ = dst[15] // early bounds check
	 129  	binary.BigEndian.PutUint32(dst[0:4], s0)
	 130  	binary.BigEndian.PutUint32(dst[4:8], s1)
	 131  	binary.BigEndian.PutUint32(dst[8:12], s2)
	 132  	binary.BigEndian.PutUint32(dst[12:16], s3)
	 133  }
	 134  
	 135  // Apply sbox0 to each byte in w.
	 136  func subw(w uint32) uint32 {
	 137  	return uint32(sbox0[w>>24])<<24 |
	 138  		uint32(sbox0[w>>16&0xff])<<16 |
	 139  		uint32(sbox0[w>>8&0xff])<<8 |
	 140  		uint32(sbox0[w&0xff])
	 141  }
	 142  
	 143  // Rotate
	 144  func rotw(w uint32) uint32 { return w<<8 | w>>24 }
	 145  
	 146  // Key expansion algorithm. See FIPS-197, Figure 11.
	 147  // Their rcon[i] is our powx[i-1] << 24.
	 148  func expandKeyGo(key []byte, enc, dec []uint32) {
	 149  	// Encryption key setup.
	 150  	var i int
	 151  	nk := len(key) / 4
	 152  	for i = 0; i < nk; i++ {
	 153  		enc[i] = binary.BigEndian.Uint32(key[4*i:])
	 154  	}
	 155  	for ; i < len(enc); i++ {
	 156  		t := enc[i-1]
	 157  		if i%nk == 0 {
	 158  			t = subw(rotw(t)) ^ (uint32(powx[i/nk-1]) << 24)
	 159  		} else if nk > 6 && i%nk == 4 {
	 160  			t = subw(t)
	 161  		}
	 162  		enc[i] = enc[i-nk] ^ t
	 163  	}
	 164  
	 165  	// Derive decryption key from encryption key.
	 166  	// Reverse the 4-word round key sets from enc to produce dec.
	 167  	// All sets but the first and last get the MixColumn transform applied.
	 168  	if dec == nil {
	 169  		return
	 170  	}
	 171  	n := len(enc)
	 172  	for i := 0; i < n; i += 4 {
	 173  		ei := n - i - 4
	 174  		for j := 0; j < 4; j++ {
	 175  			x := enc[ei+j]
	 176  			if i > 0 && i+4 < n {
	 177  				x = td0[sbox0[x>>24]] ^ td1[sbox0[x>>16&0xff]] ^ td2[sbox0[x>>8&0xff]] ^ td3[sbox0[x&0xff]]
	 178  			}
	 179  			dec[i+j] = x
	 180  		}
	 181  	}
	 182  }
	 183  

View as plain text