poly1305_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. "encoding/hex"
  7. "flag"
  8. "testing"
  9. "unsafe"
  10. )
  11. var stressFlag = flag.Bool("stress", false, "run slow stress tests")
  12. type test struct {
  13. in string
  14. key string
  15. tag string
  16. }
  17. func (t *test) Input() []byte {
  18. in, err := hex.DecodeString(t.in)
  19. if err != nil {
  20. panic(err)
  21. }
  22. return in
  23. }
  24. func (t *test) Key() [32]byte {
  25. buf, err := hex.DecodeString(t.key)
  26. if err != nil {
  27. panic(err)
  28. }
  29. var key [32]byte
  30. copy(key[:], buf[:32])
  31. return key
  32. }
  33. func (t *test) Tag() [16]byte {
  34. buf, err := hex.DecodeString(t.tag)
  35. if err != nil {
  36. panic(err)
  37. }
  38. var tag [16]byte
  39. copy(tag[:], buf[:16])
  40. return tag
  41. }
  42. func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) {
  43. var tag [16]byte
  44. for i, v := range testData {
  45. in := v.Input()
  46. if unaligned {
  47. in = unalignBytes(in)
  48. }
  49. key := v.Key()
  50. sumImpl(&tag, in, &key)
  51. if tag != v.Tag() {
  52. t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:])
  53. }
  54. }
  55. }
  56. func TestBurnin(t *testing.T) {
  57. // This test can be used to sanity-check significant changes. It can
  58. // take about many minutes to run, even on fast machines. It's disabled
  59. // by default.
  60. if !*stressFlag {
  61. t.Skip("skipping without -stress")
  62. }
  63. var key [32]byte
  64. var input [25]byte
  65. var output [16]byte
  66. for i := range key {
  67. key[i] = 1
  68. }
  69. for i := range input {
  70. input[i] = 2
  71. }
  72. for i := uint64(0); i < 1e10; i++ {
  73. Sum(&output, input[:], &key)
  74. copy(key[0:], output[:])
  75. copy(key[16:], output[:])
  76. copy(input[:], output[:])
  77. copy(input[16:], output[:])
  78. }
  79. const expected = "5e3b866aea0b636d240c83c428f84bfa"
  80. if got := hex.EncodeToString(output[:]); got != expected {
  81. t.Errorf("expected %s, got %s", expected, got)
  82. }
  83. }
  84. func TestSum(t *testing.T) { testSum(t, false, Sum) }
  85. func TestSumUnaligned(t *testing.T) { testSum(t, true, Sum) }
  86. func TestSumGeneric(t *testing.T) { testSum(t, false, sumGeneric) }
  87. func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
  88. func TestWriteGeneric(t *testing.T) { testWriteGeneric(t, false) }
  89. func TestWriteGenericUnaligned(t *testing.T) { testWriteGeneric(t, true) }
  90. func TestWrite(t *testing.T) { testWrite(t, false) }
  91. func TestWriteUnaligned(t *testing.T) { testWrite(t, true) }
  92. func testWriteGeneric(t *testing.T, unaligned bool) {
  93. for i, v := range testData {
  94. key := v.Key()
  95. input := v.Input()
  96. var out [16]byte
  97. if unaligned {
  98. input = unalignBytes(input)
  99. }
  100. h := newMACGeneric(&key)
  101. h.Write(input[:len(input)/2])
  102. h.Write(input[len(input)/2:])
  103. h.Sum(&out)
  104. if tag := v.Tag(); out != tag {
  105. t.Errorf("%d: expected %x, got %x", i, tag[:], out[:])
  106. }
  107. }
  108. }
  109. func testWrite(t *testing.T, unaligned bool) {
  110. for i, v := range testData {
  111. key := v.Key()
  112. input := v.Input()
  113. var out [16]byte
  114. if unaligned {
  115. input = unalignBytes(input)
  116. }
  117. h := New(&key)
  118. h.Write(input[:len(input)/2])
  119. h.Write(input[len(input)/2:])
  120. h.Sum(out[:0])
  121. if tag := v.Tag(); out != tag {
  122. t.Errorf("%d: expected %x, got %x", i, tag[:], out[:])
  123. }
  124. }
  125. }
  126. func benchmarkSum(b *testing.B, size int, unaligned bool) {
  127. var out [16]byte
  128. var key [32]byte
  129. in := make([]byte, size)
  130. if unaligned {
  131. in = unalignBytes(in)
  132. }
  133. b.SetBytes(int64(len(in)))
  134. b.ResetTimer()
  135. for i := 0; i < b.N; i++ {
  136. Sum(&out, in, &key)
  137. }
  138. }
  139. func benchmarkWrite(b *testing.B, size int, unaligned bool) {
  140. var key [32]byte
  141. h := New(&key)
  142. in := make([]byte, size)
  143. if unaligned {
  144. in = unalignBytes(in)
  145. }
  146. b.SetBytes(int64(len(in)))
  147. b.ResetTimer()
  148. for i := 0; i < b.N; i++ {
  149. h.Write(in)
  150. }
  151. }
  152. func Benchmark64(b *testing.B) { benchmarkSum(b, 64, false) }
  153. func Benchmark1K(b *testing.B) { benchmarkSum(b, 1024, false) }
  154. func Benchmark2M(b *testing.B) { benchmarkSum(b, 2*1024*1024, false) }
  155. func Benchmark64Unaligned(b *testing.B) { benchmarkSum(b, 64, true) }
  156. func Benchmark1KUnaligned(b *testing.B) { benchmarkSum(b, 1024, true) }
  157. func Benchmark2MUnaligned(b *testing.B) { benchmarkSum(b, 2*1024*1024, true) }
  158. func BenchmarkWrite64(b *testing.B) { benchmarkWrite(b, 64, false) }
  159. func BenchmarkWrite1K(b *testing.B) { benchmarkWrite(b, 1024, false) }
  160. func BenchmarkWrite2M(b *testing.B) { benchmarkWrite(b, 2*1024*1024, false) }
  161. func BenchmarkWrite64Unaligned(b *testing.B) { benchmarkWrite(b, 64, true) }
  162. func BenchmarkWrite1KUnaligned(b *testing.B) { benchmarkWrite(b, 1024, true) }
  163. func BenchmarkWrite2MUnaligned(b *testing.B) { benchmarkWrite(b, 2*1024*1024, true) }
  164. func unalignBytes(in []byte) []byte {
  165. out := make([]byte, len(in)+1)
  166. if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
  167. out = out[1:]
  168. } else {
  169. out = out[:len(in)]
  170. }
  171. copy(out, in)
  172. return out
  173. }