chacha_core_gen.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. //go:build generate
  2. // +build generate
  3. package main
  4. import (
  5. "fmt"
  6. "log"
  7. "os"
  8. )
  9. func writeQuarterRound(file *os.File, a, b, c, d int) {
  10. add := "x%d+=x%d\n"
  11. xor := "x=x%d^x%d\n"
  12. rotate := "x%d=(x << %d) | (x >> (32 - %d))\n"
  13. fmt.Fprintf(file, add, a, b)
  14. fmt.Fprintf(file, xor, d, a)
  15. fmt.Fprintf(file, rotate, d, 16, 16)
  16. fmt.Fprintf(file, add, c, d)
  17. fmt.Fprintf(file, xor, b, c)
  18. fmt.Fprintf(file, rotate, b, 12, 12)
  19. fmt.Fprintf(file, add, a, b)
  20. fmt.Fprintf(file, xor, d, a)
  21. fmt.Fprintf(file, rotate, d, 8, 8)
  22. fmt.Fprintf(file, add, c, d)
  23. fmt.Fprintf(file, xor, b, c)
  24. fmt.Fprintf(file, rotate, b, 7, 7)
  25. }
  26. func writeChacha20Block(file *os.File) {
  27. fmt.Fprintln(file, `
  28. func ChaCha20Block(s *[16]uint32, out []byte, rounds int) {
  29. var x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15 = s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],s[8],s[9],s[10],s[11],s[12],s[13],s[14],s[15]
  30. for i := 0; i < rounds; i+=2 {
  31. var x uint32
  32. `)
  33. writeQuarterRound(file, 0, 4, 8, 12)
  34. writeQuarterRound(file, 1, 5, 9, 13)
  35. writeQuarterRound(file, 2, 6, 10, 14)
  36. writeQuarterRound(file, 3, 7, 11, 15)
  37. writeQuarterRound(file, 0, 5, 10, 15)
  38. writeQuarterRound(file, 1, 6, 11, 12)
  39. writeQuarterRound(file, 2, 7, 8, 13)
  40. writeQuarterRound(file, 3, 4, 9, 14)
  41. fmt.Fprintln(file, "}")
  42. for i := 0; i < 16; i++ {
  43. fmt.Fprintf(file, "binary.LittleEndian.PutUint32(out[%d:%d], s[%d]+x%d)\n", i*4, i*4+4, i, i)
  44. }
  45. fmt.Fprintln(file, "}")
  46. fmt.Fprintln(file)
  47. }
  48. func main() {
  49. file, err := os.OpenFile("chacha_core.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
  50. if err != nil {
  51. log.Fatalf("Failed to generate chacha_core.go: %v", err)
  52. }
  53. defer file.Close()
  54. fmt.Fprintln(file, "package internal")
  55. fmt.Fprintln(file)
  56. fmt.Fprintln(file, "import \"encoding/binary\"")
  57. fmt.Fprintln(file)
  58. writeChacha20Block(file)
  59. }