The current ARM implementation assumes that the input message is memory aligned and so it can cause alignment fault when it is not enabled. Also it may generate incorrect outputs in ARMv5. This change fixes this issue by temporarily copying the input to a local aligned space. Although there may be a better way to handle unaligned access, this would be a safe way in all ARM versions. This change also added a test and benchmarks with unaligned data. The benchmark result on RasberryPI 2 is Benchmark64 2000000 812 ns/op 78.81 MB/s Benchmark1K 200000 7809 ns/op 131.12 MB/s Benchmark64Unaligned 2000000 967 ns/op 66.13 MB/s Benchmark1KUnaligned 200000 10316 ns/op 99.26 MB/s Change-Id: I189cc1b7bb6c67a04c9877271fb27326f2896e82 Reviewed-on: https://go-review.googlesource.com/12797 Reviewed-by: Adam Langley <agl@golang.org>
87 lines
2.0 KiB
Go
87 lines
2.0 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package poly1305
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
var testData = []struct {
|
|
in, k, correct []byte
|
|
}{
|
|
{
|
|
[]byte("Hello world!"),
|
|
[]byte("this is 32-byte key for Poly1305"),
|
|
[]byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
|
|
},
|
|
{
|
|
make([]byte, 32),
|
|
[]byte("this is 32-byte key for Poly1305"),
|
|
[]byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
|
|
},
|
|
{
|
|
make([]byte, 2007),
|
|
[]byte("this is 32-byte key for Poly1305"),
|
|
[]byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
|
|
},
|
|
{
|
|
make([]byte, 2007),
|
|
make([]byte, 32),
|
|
make([]byte, 16),
|
|
},
|
|
}
|
|
|
|
func testSum(t *testing.T, unaligned bool) {
|
|
var out [16]byte
|
|
var key [32]byte
|
|
|
|
for i, v := range testData {
|
|
in := v.in
|
|
if unaligned {
|
|
in = unalignBytes(in)
|
|
}
|
|
copy(key[:], v.k)
|
|
Sum(&out, in, &key)
|
|
if !bytes.Equal(out[:], v.correct) {
|
|
t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSum(t *testing.T) { testSum(t, false) }
|
|
func TestSumUnaligned(t *testing.T) { testSum(t, true) }
|
|
|
|
func benchmark(b *testing.B, size int, unaligned bool) {
|
|
var out [16]byte
|
|
var key [32]byte
|
|
in := make([]byte, size)
|
|
if unaligned {
|
|
in = unalignBytes(in)
|
|
}
|
|
b.SetBytes(int64(len(in)))
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
Sum(&out, in, &key)
|
|
}
|
|
}
|
|
|
|
func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
|
|
func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
|
|
func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
|
|
func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
|
|
|
|
func unalignBytes(in []byte) []byte {
|
|
out := make([]byte, len(in)+1)
|
|
if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
|
|
out = out[1:]
|
|
} else {
|
|
out = out[:len(in)]
|
|
}
|
|
copy(out, in)
|
|
return out
|
|
}
|