You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
5.0 KiB

  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. package poly1305
  5. import (
  6. "bytes"
  7. "encoding/hex"
  8. "flag"
  9. "testing"
  10. "unsafe"
  11. )
  12. var stressFlag = flag.Bool("stress", false, "run slow stress tests")
  13. var testData = []struct {
  14. in, k, correct []byte
  15. }{
  16. {
  17. []byte("Hello world!"),
  18. []byte("this is 32-byte key for Poly1305"),
  19. []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
  20. },
  21. {
  22. make([]byte, 32),
  23. []byte("this is 32-byte key for Poly1305"),
  24. []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
  25. },
  26. {
  27. make([]byte, 2007),
  28. []byte("this is 32-byte key for Poly1305"),
  29. []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
  30. },
  31. {
  32. make([]byte, 2007),
  33. make([]byte, 32),
  34. make([]byte, 16),
  35. },
  36. {
  37. // This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/.
  38. []byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29},
  39. []byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
  40. []byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
  41. },
  42. {
  43. // This test generates a result of (2^130-1) % (2^130-5).
  44. []byte{
  45. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  46. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  47. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  48. },
  49. []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  50. []byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  51. },
  52. {
  53. // This test generates a result of (2^130-6) % (2^130-5).
  54. []byte{
  55. 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  56. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  58. },
  59. []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  60. []byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  61. },
  62. {
  63. // This test generates a result of (2^130-5) % (2^130-5).
  64. []byte{
  65. 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  68. },
  69. []byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  70. []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  71. },
  72. }
  73. func testSum(t *testing.T, unaligned bool) {
  74. var out [16]byte
  75. var key [32]byte
  76. for i, v := range testData {
  77. in := v.in
  78. if unaligned {
  79. in = unalignBytes(in)
  80. }
  81. copy(key[:], v.k)
  82. Sum(&out, in, &key)
  83. if !bytes.Equal(out[:], v.correct) {
  84. t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
  85. }
  86. }
  87. }
  88. func TestBurnin(t *testing.T) {
  89. // This test can be used to sanity-check significant changes. It can
  90. // take about many minutes to run, even on fast machines. It's disabled
  91. // by default.
  92. if !*stressFlag {
  93. t.Skip("skipping without -stress")
  94. }
  95. var key [32]byte
  96. var input [25]byte
  97. var output [16]byte
  98. for i := range key {
  99. key[i] = 1
  100. }
  101. for i := range input {
  102. input[i] = 2
  103. }
  104. for i := uint64(0); i < 1e10; i++ {
  105. Sum(&output, input[:], &key)
  106. copy(key[0:], output[:])
  107. copy(key[16:], output[:])
  108. copy(input[:], output[:])
  109. copy(input[16:], output[:])
  110. }
  111. const expected = "5e3b866aea0b636d240c83c428f84bfa"
  112. if got := hex.EncodeToString(output[:]); got != expected {
  113. t.Errorf("expected %s, got %s", expected, got)
  114. }
  115. }
  116. func TestSum(t *testing.T) { testSum(t, false) }
  117. func TestSumUnaligned(t *testing.T) { testSum(t, true) }
  118. func benchmark(b *testing.B, size int, unaligned bool) {
  119. var out [16]byte
  120. var key [32]byte
  121. in := make([]byte, size)
  122. if unaligned {
  123. in = unalignBytes(in)
  124. }
  125. b.SetBytes(int64(len(in)))
  126. b.ResetTimer()
  127. for i := 0; i < b.N; i++ {
  128. Sum(&out, in, &key)
  129. }
  130. }
  131. func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
  132. func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
  133. func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
  134. func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
  135. func unalignBytes(in []byte) []byte {
  136. out := make([]byte, len(in)+1)
  137. if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
  138. out = out[1:]
  139. } else {
  140. out = out[:len(in)]
  141. }
  142. copy(out, in)
  143. return out
  144. }