gen.mx raw
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 //go:build ignore
6
7 // This program generates md5block.go
8 // Invoke as
9 //
10 // go run gen.go -output md5block.go
11
12 package main
13
14 import (
15 "bytes"
16 "flag"
17 "go/format"
18 "log"
19 "os"
20 "text/template"
21 )
22
23 var filename = flag.String("output", "md5block.go", "output file name")
24
25 func main() {
26 flag.Parse()
27
28 var buf bytes.Buffer
29
30 t := template.Must(template.New("main").Funcs(funcs).Parse(program))
31 if err := t.Execute(&buf, data); err != nil {
32 log.Fatal(err)
33 }
34
35 data, err := format.Source(buf.Bytes())
36 if err != nil {
37 log.Fatal(err)
38 }
39 err = os.WriteFile(*filename, data, 0644)
40 if err != nil {
41 log.Fatal(err)
42 }
43 }
44
45 type Data struct {
46 a, b, c, d string
47 Shift1 []int
48 Shift2 []int
49 Shift3 []int
50 Shift4 []int
51 Table1 []uint32
52 Table2 []uint32
53 Table3 []uint32
54 Table4 []uint32
55 }
56
57 var funcs = template.FuncMap{
58 "dup": dup,
59 "relabel": relabel,
60 "rotate": rotate,
61 "idx": idx,
62 "seq": seq,
63 }
64
65 func dup(count int, x []int) []int {
66 var out []int
67 for i := 0; i < count; i++ {
68 out = append(out, x...)
69 }
70 return out
71 }
72
73 func relabel(s string) string {
74 return bytes.NewReplacer("arg0", data.a, "arg1", data.b, "arg2", data.c, "arg3", data.d).Replace(s)
75 }
76
77 func rotate() string {
78 data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c
79 return "" // no output
80 }
81
82 func idx(round, index int) int {
83 v := 0
84 switch round {
85 case 1:
86 v = index
87 case 2:
88 v = (1 + 5*index) & 15
89 case 3:
90 v = (5 + 3*index) & 15
91 case 4:
92 v = (7 * index) & 15
93 }
94 return v
95 }
96
97 func seq(i int) []int {
98 s := []int{:i}
99 for i := range s {
100 s[i] = i
101 }
102 return s
103 }
104
105 var data = Data{
106 a: "a",
107 b: "b",
108 c: "c",
109 d: "d",
110 Shift1: []int{7, 12, 17, 22},
111 Shift2: []int{5, 9, 14, 20},
112 Shift3: []int{4, 11, 16, 23},
113 Shift4: []int{6, 10, 15, 21},
114
115 // table[i] = int((1<<32) * abs(sin(i+1 radians))).
116 Table1: []uint32{
117 // round 1
118 0xd76aa478,
119 0xe8c7b756,
120 0x242070db,
121 0xc1bdceee,
122 0xf57c0faf,
123 0x4787c62a,
124 0xa8304613,
125 0xfd469501,
126 0x698098d8,
127 0x8b44f7af,
128 0xffff5bb1,
129 0x895cd7be,
130 0x6b901122,
131 0xfd987193,
132 0xa679438e,
133 0x49b40821,
134 },
135 Table2: []uint32{
136 // round 2
137 0xf61e2562,
138 0xc040b340,
139 0x265e5a51,
140 0xe9b6c7aa,
141 0xd62f105d,
142 0x2441453,
143 0xd8a1e681,
144 0xe7d3fbc8,
145 0x21e1cde6,
146 0xc33707d6,
147 0xf4d50d87,
148 0x455a14ed,
149 0xa9e3e905,
150 0xfcefa3f8,
151 0x676f02d9,
152 0x8d2a4c8a,
153 },
154 Table3: []uint32{
155 // round3
156 0xfffa3942,
157 0x8771f681,
158 0x6d9d6122,
159 0xfde5380c,
160 0xa4beea44,
161 0x4bdecfa9,
162 0xf6bb4b60,
163 0xbebfbc70,
164 0x289b7ec6,
165 0xeaa127fa,
166 0xd4ef3085,
167 0x4881d05,
168 0xd9d4d039,
169 0xe6db99e5,
170 0x1fa27cf8,
171 0xc4ac5665,
172 },
173 Table4: []uint32{
174 // round 4
175 0xf4292244,
176 0x432aff97,
177 0xab9423a7,
178 0xfc93a039,
179 0x655b59c3,
180 0x8f0ccc92,
181 0xffeff47d,
182 0x85845dd1,
183 0x6fa87e4f,
184 0xfe2ce6e0,
185 0xa3014314,
186 0x4e0811a1,
187 0xf7537e82,
188 0xbd3af235,
189 0x2ad7d2bb,
190 0xeb86d391,
191 },
192 }
193
194 var program = `// Copyright 2013 The Go Authors. All rights reserved.
195 // Use of this source code is governed by a BSD-style
196 // license that can be found in the LICENSE file.
197
198 // Code generated by go run gen.go -output md5block.go; DO NOT EDIT.
199
200 package md5
201
202 import (
203 "internal/byteorder"
204 "math/bits"
205 )
206
207 func blockGeneric(dig *digest, p []byte) {
208 // load state
209 a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3]
210
211 for i := 0; i <= len(p)-BlockSize; i += BlockSize {
212 // eliminate bounds checks on p
213 q := p[i:]
214 q = q[:BlockSize:BlockSize]
215
216 // save current state
217 aa, bb, cc, dd := a, b, c, d
218
219 // load input block
220 {{range $i := seq 16 -}}
221 {{printf "x%x := byteorder.LEUint32(q[4*%#x:])" $i $i}}
222 {{end}}
223
224 // round 1
225 {{range $i, $s := dup 4 .Shift1 -}}
226 {{printf "arg0 = arg1 + bits.RotateLeft32((((arg2^arg3)&arg1)^arg3)+arg0+x%x+%#08x, %d)" (idx 1 $i) (index $.Table1 $i) $s | relabel}}
227 {{rotate -}}
228 {{end}}
229
230 // round 2
231 {{range $i, $s := dup 4 .Shift2 -}}
232 {{printf "arg0 = arg1 + bits.RotateLeft32((((arg1^arg2)&arg3)^arg2)+arg0+x%x+%#08x, %d)" (idx 2 $i) (index $.Table2 $i) $s | relabel}}
233 {{rotate -}}
234 {{end}}
235
236 // round 3
237 {{range $i, $s := dup 4 .Shift3 -}}
238 {{printf "arg0 = arg1 + bits.RotateLeft32((arg1^arg2^arg3)+arg0+x%x+%#08x, %d)" (idx 3 $i) (index $.Table3 $i) $s | relabel}}
239 {{rotate -}}
240 {{end}}
241
242 // round 4
243 {{range $i, $s := dup 4 .Shift4 -}}
244 {{printf "arg0 = arg1 + bits.RotateLeft32((arg2^(arg1|^arg3))+arg0+x%x+%#08x, %d)" (idx 4 $i) (index $.Table4 $i) $s | relabel}}
245 {{rotate -}}
246 {{end}}
247
248 // add saved state
249 a += aa
250 b += bb
251 c += cc
252 d += dd
253 }
254
255 // save state
256 dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d
257 }
258 `
259