github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/crypto/md5/gen.go (about)

     1  // Copyright 2012 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  // +build ignore
     6  
     7  // This program generates md5block.go
     8  // Invoke as
     9  //
    10  //	go run gen.go [-full] |gofmt >md5block.go
    11  //
    12  // The -full flag causes the generated code to do a full
    13  // (16x) unrolling instead of a 4x unrolling.
    14  
    15  package main
    16  
    17  import (
    18  	"flag"
    19  	"log"
    20  	"os"
    21  	"strings"
    22  	"text/template"
    23  )
    24  
    25  func main() {
    26  	flag.Parse()
    27  
    28  	t := template.Must(template.New("main").Funcs(funcs).Parse(program))
    29  	if err := t.Execute(os.Stdout, data); err != nil {
    30  		log.Fatal(err)
    31  	}
    32  }
    33  
    34  type Data struct {
    35  	a, b, c, d string
    36  	Shift1     []int
    37  	Shift2     []int
    38  	Shift3     []int
    39  	Shift4     []int
    40  	Table1     []uint32
    41  	Table2     []uint32
    42  	Table3     []uint32
    43  	Table4     []uint32
    44  	Full       bool
    45  }
    46  
    47  var funcs = template.FuncMap{
    48  	"dup":     dup,
    49  	"relabel": relabel,
    50  	"rotate":  rotate,
    51  }
    52  
    53  func dup(count int, x []int) []int {
    54  	var out []int
    55  	for i := 0; i < count; i++ {
    56  		out = append(out, x...)
    57  	}
    58  	return out
    59  }
    60  
    61  func relabel(s string) string {
    62  	return strings.NewReplacer("a", data.a, "b", data.b, "c", data.c, "d", data.d).Replace(s)
    63  }
    64  
    65  func rotate() string {
    66  	data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
    67  	return "" // no output
    68  }
    69  
    70  func init() {
    71  	flag.BoolVar(&data.Full, "full", false, "complete unrolling")
    72  }
    73  
    74  var data = Data{
    75  	a:      "a",
    76  	b:      "b",
    77  	c:      "c",
    78  	d:      "d",
    79  	Shift1: []int{7, 12, 17, 22},
    80  	Shift2: []int{5, 9, 14, 20},
    81  	Shift3: []int{4, 11, 16, 23},
    82  	Shift4: []int{6, 10, 15, 21},
    83  
    84  	// table[i] = int((1<<32) * abs(sin(i+1 radians))).
    85  	Table1: []uint32{
    86  		// round 1
    87  		0xd76aa478,
    88  		0xe8c7b756,
    89  		0x242070db,
    90  		0xc1bdceee,
    91  		0xf57c0faf,
    92  		0x4787c62a,
    93  		0xa8304613,
    94  		0xfd469501,
    95  		0x698098d8,
    96  		0x8b44f7af,
    97  		0xffff5bb1,
    98  		0x895cd7be,
    99  		0x6b901122,
   100  		0xfd987193,
   101  		0xa679438e,
   102  		0x49b40821,
   103  	},
   104  	Table2: []uint32{
   105  		// round 2
   106  		0xf61e2562,
   107  		0xc040b340,
   108  		0x265e5a51,
   109  		0xe9b6c7aa,
   110  		0xd62f105d,
   111  		0x2441453,
   112  		0xd8a1e681,
   113  		0xe7d3fbc8,
   114  		0x21e1cde6,
   115  		0xc33707d6,
   116  		0xf4d50d87,
   117  		0x455a14ed,
   118  		0xa9e3e905,
   119  		0xfcefa3f8,
   120  		0x676f02d9,
   121  		0x8d2a4c8a,
   122  	},
   123  	Table3: []uint32{
   124  		// round3
   125  		0xfffa3942,
   126  		0x8771f681,
   127  		0x6d9d6122,
   128  		0xfde5380c,
   129  		0xa4beea44,
   130  		0x4bdecfa9,
   131  		0xf6bb4b60,
   132  		0xbebfbc70,
   133  		0x289b7ec6,
   134  		0xeaa127fa,
   135  		0xd4ef3085,
   136  		0x4881d05,
   137  		0xd9d4d039,
   138  		0xe6db99e5,
   139  		0x1fa27cf8,
   140  		0xc4ac5665,
   141  	},
   142  	Table4: []uint32{
   143  		// round 4
   144  		0xf4292244,
   145  		0x432aff97,
   146  		0xab9423a7,
   147  		0xfc93a039,
   148  		0x655b59c3,
   149  		0x8f0ccc92,
   150  		0xffeff47d,
   151  		0x85845dd1,
   152  		0x6fa87e4f,
   153  		0xfe2ce6e0,
   154  		0xa3014314,
   155  		0x4e0811a1,
   156  		0xf7537e82,
   157  		0xbd3af235,
   158  		0x2ad7d2bb,
   159  		0xeb86d391,
   160  	},
   161  }
   162  
   163  var program = `// Copyright 2013 The Go Authors. All rights reserved.
   164  // Use of this source code is governed by a BSD-style
   165  // license that can be found in the LICENSE file.
   166  
   167  // DO NOT EDIT.
   168  // Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go
   169  
   170  package md5
   171  
   172  import (
   173  	"unsafe"
   174  	"runtime"
   175  )
   176  
   177  {{if not .Full}}
   178  	var t1 = [...]uint32{
   179  	{{range .Table1}}{{printf "\t%#x,\n" .}}{{end}}
   180  	}
   181  	
   182  	var t2 = [...]uint32{
   183  	{{range .Table2}}{{printf "\t%#x,\n" .}}{{end}}
   184  	}
   185  	
   186  	var t3 = [...]uint32{
   187  	{{range .Table3}}{{printf "\t%#x,\n" .}}{{end}}
   188  	}
   189  	
   190  	var t4 = [...]uint32{
   191  	{{range .Table4}}{{printf "\t%#x,\n" .}}{{end}}
   192  	}
   193  {{end}}
   194  
   195  const x86 = runtime.GOARCH == "amd64" || runtime.GOARCH == "386"
   196  
   197  var littleEndian bool
   198  
   199  func init() {
   200  	x := uint32(0x04030201)
   201  	y := [4]byte{0x1, 0x2, 0x3, 0x4}
   202  	littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y
   203  }
   204  
   205  func blockGeneric(dig *digest, p []byte) {
   206  	a := dig.s[0]
   207  	b := dig.s[1]
   208  	c := dig.s[2]
   209  	d := dig.s[3]
   210  	var X *[16]uint32
   211  	var xbuf [16]uint32
   212  	for len(p) >= chunk {
   213  		aa, bb, cc, dd := a, b, c, d
   214  
   215  		// This is a constant condition - it is not evaluated on each iteration.
   216  		if x86 {
   217  			// MD5 was designed so that x86 processors can just iterate
   218  			// over the block data directly as uint32s, and we generate
   219  			// less code and run 1.3x faster if we take advantage of that.
   220  			// My apologies.
   221  			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
   222  		} else if littleEndian && uintptr(unsafe.Pointer(&p[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
   223  			X = (*[16]uint32)(unsafe.Pointer(&p[0]))
   224  		} else {
   225  			X = &xbuf
   226  			j := 0
   227  			for i := 0; i < 16; i++ {
   228  				X[i&15] = uint32(p[j]) | uint32(p[j+1])<<8 | uint32(p[j+2])<<16 | uint32(p[j+3])<<24
   229  				j += 4
   230  			}
   231  		}
   232  
   233  		{{if .Full}}
   234  			// Round 1.
   235  			{{range $i, $s := dup 4 .Shift1}}
   236  				{{index $.Table1 $i | printf "a += (((c^d)&b)^d) + X[%d] + %d" $i | relabel}}
   237  				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   238  				{{rotate}}
   239  			{{end}}
   240  	
   241  			// Round 2.
   242  			{{range $i, $s := dup 4 .Shift2}}
   243  				{{index $.Table2 $i | printf "a += (((b^c)&d)^c) + X[(1+5*%d)&15] + %d" $i | relabel}}
   244  				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   245  				{{rotate}}
   246  			{{end}}
   247  	
   248  			// Round 3.
   249  			{{range $i, $s := dup 4 .Shift3}}
   250  				{{index $.Table3 $i | printf "a += (b^c^d) + X[(5+3*%d)&15] + %d" $i | relabel}}
   251  				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   252  				{{rotate}}
   253  			{{end}}
   254  	
   255  			// Round 4.
   256  			{{range $i, $s := dup 4 .Shift4}}
   257  				{{index $.Table4 $i | printf "a += (c^(b|^d)) + X[(7*%d)&15] + %d" $i | relabel}}
   258  				{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   259  				{{rotate}}
   260  			{{end}}
   261  		{{else}}
   262  			// Round 1.
   263  			for i := uint(0); i < 16; {
   264  				{{range $s := .Shift1}}
   265  					{{printf "a += (((c^d)&b)^d) + X[i&15] + t1[i&15]" | relabel}}
   266  					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   267  					i++
   268  					{{rotate}}
   269  				{{end}}
   270  			}
   271  	
   272  			// Round 2.
   273  			for i := uint(0); i < 16; {
   274  				{{range $s := .Shift2}}
   275  					{{printf "a += (((b^c)&d)^c) + X[(1+5*i)&15] + t2[i&15]" | relabel}}
   276  					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   277  					i++
   278  					{{rotate}}
   279  				{{end}}
   280  			}
   281  	
   282  			// Round 3.
   283  			for i := uint(0); i < 16; {
   284  				{{range $s := .Shift3}}
   285  					{{printf "a += (b^c^d) + X[(5+3*i)&15] + t3[i&15]" | relabel}}
   286  					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   287  					i++
   288  					{{rotate}}
   289  				{{end}}
   290  			}
   291  	
   292  			// Round 4.
   293  			for i := uint(0); i < 16; {
   294  				{{range $s := .Shift4}}
   295  					{{printf "a += (c^(b|^d)) + X[(7*i)&15] + t4[i&15]" | relabel}}
   296  					{{printf "a = a<<%d | a>>(32-%d) + b" $s $s | relabel}}
   297  					i++
   298  					{{rotate}}
   299  				{{end}}
   300  			}
   301  		{{end}}
   302  
   303  		a += aa
   304  		b += bb
   305  		c += cc
   306  		d += dd
   307  
   308  		p = p[chunk:]
   309  	}
   310  
   311  	dig.s[0] = a
   312  	dig.s[1] = b
   313  	dig.s[2] = c
   314  	dig.s[3] = d
   315  }
   316  `