...

Source file src/pkg/crypto/aes/block.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	// 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 <vincent.rijmen@esat.kuleuven.ac.be>
    15	//	@author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
    16	//	@author Paulo Barreto <paulo.barreto@terra.com.br>
    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