From 9ee887823d78b9795d0951606c2770f0f5836470 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 27 May 2015 10:59:59 -0400 Subject: [PATCH] Take advantage of Go 1.5 optimized zeroing. Closes #286. --- internal/zero/array.go | 27 +++++++++++++++ internal/zero/doc.go | 3 ++ internal/zero/slice.go | 47 +++++++++++++++++++++++++++ internal/zero/{zero.go => slice14.go} | 25 +++++++------- 4 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 internal/zero/array.go create mode 100644 internal/zero/doc.go create mode 100644 internal/zero/slice.go rename internal/zero/{zero.go => slice14.go} (78%) diff --git a/internal/zero/array.go b/internal/zero/array.go new file mode 100644 index 0000000..5a04558 --- /dev/null +++ b/internal/zero/array.go @@ -0,0 +1,27 @@ +// Copyright (c) 2015 The btcsuite developers +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +package zero + +// Bytea32 clears the 32-byte array by filling it with the zero value. +// This is used to explicitly clear private key material from memory. +func Bytea32(b *[32]byte) { + *b = [32]byte{} +} + +// Bytea64 clears the 64-byte array by filling it with the zero value. +// This is used to explicitly clear sensitive material from memory. +func Bytea64(b *[64]byte) { + *b = [64]byte{} +} diff --git a/internal/zero/doc.go b/internal/zero/doc.go new file mode 100644 index 0000000..457b8e3 --- /dev/null +++ b/internal/zero/doc.go @@ -0,0 +1,3 @@ +// Package zero contains functions to clear data from byte slices and +// multi-precision integers. +package zero diff --git a/internal/zero/slice.go b/internal/zero/slice.go new file mode 100644 index 0000000..bc486d5 --- /dev/null +++ b/internal/zero/slice.go @@ -0,0 +1,47 @@ +// Copyright (c) 2015 The btcsuite developers +// +// Permission to use, copy, modify, and distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +// This file implements range-based zeroing, which as of Go 1.5 is +// optimized using a Duff's device. See slice14.go for an implementation +// optimized for previous Go versions. +// +// +build !go1.3,!go1.4 + +package zero + +import "math/big" + +// Bytes sets all bytes in the passed slice to zero. This is used to +// explicitly clear private key material from memory. +// +// In general, prefer to use the fixed-sized zeroing functions (Bytea*) +// when zeroing bytes as they are much more efficient than the variable +// sized zeroing func Bytes. +func Bytes(b []byte) { + for i := range b { + b[i] = 0 + } +} + +// BigInt sets all bytes in the passed big int to zero and then sets the +// value to 0. This differs from simply setting the value in that it +// specifically clears the underlying bytes whereas simply setting the value +// does not. This is mostly useful to forcefully clear private keys. +func BigInt(x *big.Int) { + b := x.Bits() + for i := range b { + b[i] = 0 + } + x.SetInt64(0) +} diff --git a/internal/zero/zero.go b/internal/zero/slice14.go similarity index 78% rename from internal/zero/zero.go rename to internal/zero/slice14.go index 293b028..9c9eb6c 100644 --- a/internal/zero/zero.go +++ b/internal/zero/slice14.go @@ -12,8 +12,17 @@ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -// Package zero contains functions to clear data from byte slices and -// multi-precision integers. +// Go >= 1.5 optimizes range-based zeroing of the form: +// +// for i := range slice { +// slice[i] = 0 +// } +// +// to an optimized implementation using a Duff's device, but older versions +// do not and benefit from this custom implementation. +// +// +build go1.3 go1.4 + package zero import ( @@ -35,18 +44,6 @@ func Bytes(b []byte) { } } -// Bytea32 clears the 32-byte array by filling it with the zero value. -// This is used to explicitly clear private key material from memory. -func Bytea32(b *[32]byte) { - *b = [32]byte{} -} - -// Bytea64 clears the 64-byte array by filling it with the zero value. -// This is used to explicitly clear sensitive material from memory. -func Bytea64(b *[64]byte) { - *b = [64]byte{} -} - // BigInt sets all bytes in the passed big int to zero and then sets the // value to 0. This differs from simply setting the value in that it // specifically clears the underlying bytes whereas simply setting the value