github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/crypto/poly1305/poly1305_test.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  package poly1305
     6  
     7  import (
     8  	"encoding/hex"
     9  	"flag"
    10  	"testing"
    11  	"unsafe"
    12  )
    13  
    14  var stressFlag = flag.Bool("stress", false, "run slow stress tests")
    15  
    16  type test struct {
    17  	in  string
    18  	key string
    19  	tag string
    20  }
    21  
    22  func (t *test) Input() []byte {
    23  	in, err := hex.DecodeString(t.in)
    24  	if err != nil {
    25  		panic(err)
    26  	}
    27  	return in
    28  }
    29  
    30  func (t *test) Key() [32]byte {
    31  	buf, err := hex.DecodeString(t.key)
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  	var key [32]byte
    36  	copy(key[:], buf[:32])
    37  	return key
    38  }
    39  
    40  func (t *test) Tag() [16]byte {
    41  	buf, err := hex.DecodeString(t.tag)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  	var tag [16]byte
    46  	copy(tag[:], buf[:16])
    47  	return tag
    48  }
    49  
    50  func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) {
    51  	var tag [16]byte
    52  	for i, v := range testData {
    53  		in := v.Input()
    54  		if unaligned {
    55  			in = unalignBytes(in)
    56  		}
    57  		key := v.Key()
    58  		sumImpl(&tag, in, &key)
    59  		if tag != v.Tag() {
    60  			t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:])
    61  		}
    62  	}
    63  }
    64  
    65  func TestBurnin(t *testing.T) {
    66  	// This test can be used to sanity-check significant changes. It can
    67  	// take about many minutes to run, even on fast machines. It's disabled
    68  	// by default.
    69  	if !*stressFlag {
    70  		t.Skip("skipping without -stress")
    71  	}
    72  
    73  	var key [32]byte
    74  	var input [25]byte
    75  	var output [16]byte
    76  
    77  	for i := range key {
    78  		key[i] = 1
    79  	}
    80  	for i := range input {
    81  		input[i] = 2
    82  	}
    83  
    84  	for i := uint64(0); i < 1e10; i++ {
    85  		Sum(&output, input[:], &key)
    86  		copy(key[0:], output[:])
    87  		copy(key[16:], output[:])
    88  		copy(input[:], output[:])
    89  		copy(input[16:], output[:])
    90  	}
    91  
    92  	const expected = "5e3b866aea0b636d240c83c428f84bfa"
    93  	if got := hex.EncodeToString(output[:]); got != expected {
    94  		t.Errorf("expected %s, got %s", expected, got)
    95  	}
    96  }
    97  
    98  func TestSum(t *testing.T)                 { testSum(t, false, Sum) }
    99  func TestSumUnaligned(t *testing.T)        { testSum(t, true, Sum) }
   100  func TestSumGeneric(t *testing.T)          { testSum(t, false, sumGeneric) }
   101  func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
   102  
   103  func benchmark(b *testing.B, size int, unaligned bool) {
   104  	var out [16]byte
   105  	var key [32]byte
   106  	in := make([]byte, size)
   107  	if unaligned {
   108  		in = unalignBytes(in)
   109  	}
   110  	b.SetBytes(int64(len(in)))
   111  	b.ResetTimer()
   112  	for i := 0; i < b.N; i++ {
   113  		Sum(&out, in, &key)
   114  	}
   115  }
   116  
   117  func Benchmark64(b *testing.B)          { benchmark(b, 64, false) }
   118  func Benchmark1K(b *testing.B)          { benchmark(b, 1024, false) }
   119  func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
   120  func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
   121  func Benchmark2M(b *testing.B)          { benchmark(b, 2097152, true) }
   122  
   123  func unalignBytes(in []byte) []byte {
   124  	out := make([]byte, len(in)+1)
   125  	if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
   126  		out = out[1:]
   127  	} else {
   128  		out = out[:len(in)]
   129  	}
   130  	copy(out, in)
   131  	return out
   132  }