Source

sha3 / gen.go

Full commit
// Copyright 2012 Eric Roshan-Eisner. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Script to unroll the rounds of the core computation of Keccak.
// Generate like so: go run gen.go | gofmt > bench.go

// +build ignore

package main

import (
	"fmt"
	"io"
	"os"
)

var rotc = [24]uint{
	1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
	27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
}

var piln = [24]int{
	10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
	15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
}

func main() {
	unrollblock(os.Stdout)
}

func unrollblock(w io.Writer) {
	fmt.Fprintln(w, `// Copyright 2012 Eric Roshan-Eisner. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sha3

var rndc = [24]uint64{
	0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
	0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
	0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
	0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
	0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
	0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
	0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
	0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
}

func rotl(x uint64, r uint) uint64 {
	return (x << r) | (x >> (64 - r))
}

func block(st *[25]uint64) {
	var (
		t, bc0,bc1,bc2,bc3,bc4 uint64
	)
	for round := 0; round < 24; round++ {`)
	theta(w)
	rhopi(w)
	chi(w)
	fmt.Fprintln(w, `
		//  Iota
		st[0] ^= rndc[round]
	}
}`)
}

func theta(w io.Writer) {
	fmt.Fprintln(w, "// Theta")
	for i := 0; i < 5; i++ {
		fmt.Fprintf(w, "bc%d = st[%d]^st[%d]^st[%d]^st[%d]^st[%d]\n",
			i, i, i+5, i+10, i+15, i+20)
	}
	for i := 0; i < 5; i++ {
		fmt.Fprintf(w, "t = bc%d ^ rotl(bc%d, 1)\n", (i+4)%5, (i+1)%5)
		for j := 0; j < 25; j += 5 {
			fmt.Fprintf(w, "st[%d] ^= t\n", i+j)
		}
	}
}

func rhopi(w io.Writer) {
	fmt.Fprintln(w, `
	// Rho Pi
	t = st[1]`)
	for i := 0; i < 24; i++ {
		fmt.Fprintf(w, `
		bc0 = st[%d]
		st[%d] = rotl(t, %d)
		t = bc0`, piln[i], piln[i], rotc[i])
	}
}

func chi(w io.Writer) {
	fmt.Fprintln(w, "\n\n//  Chi")
	for j := 0; j < 25; j += 5 {
		for i := 0; i < 5; i++ {
			fmt.Fprintf(w, "bc%d = st[%d]\n", i, i+j)
		}
		for i := 0; i < 5; i++ {
			fmt.Fprintf(w, "st[%d] ^= bc%d &^ bc%d\n", i+j, (i+2)%5, (i+1)%5)
		}
	}
}