From faeffac0cf67c02ffd79aa90d2be8e56ed1b84d8 Mon Sep 17 00:00:00 2001 From: sean Date: Sat, 20 May 2023 18:08:04 +0200 Subject: [PATCH] Fix to/from array conversions for windows uint is **at least** 32 bit integer, according to the standard. on windows, the uint has 64 bits, as in linux, but: C.sizeof_ulong is 0x4 on windows. ASAN does not like that. but even if the value is stored, the code can't read it properly, because bytesToUlong checks `if sliceSize > C.sizeof_ulong` --- common.go | 39 +++++++++++++++++++++------------------ common_test.go | 8 +++++++- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/common.go b/common.go index 1823c17..2daba89 100644 --- a/common.go +++ b/common.go @@ -24,35 +24,38 @@ package crypto11 import ( "C" "encoding/asn1" + "encoding/binary" + "math" "math/big" - "unsafe" "github.com/miekg/pkcs11" "github.com/pkg/errors" ) func ulongToBytes(n uint) []byte { - return C.GoBytes(unsafe.Pointer(&n), C.sizeof_ulong) // ugh! + if n > math.MaxUint32 { + bytes := make([]byte, 8) + nn := uint64(n) + binary.LittleEndian.PutUint64(bytes, nn) + return bytes + } + bytes := make([]byte, 4) + nn := uint32(n) + binary.LittleEndian.PutUint32(bytes, nn) + return bytes } func bytesToUlong(bs []byte) (n uint) { - sliceSize := len(bs) - if sliceSize == 0 { - return 0 - } - - value := *(*uint)(unsafe.Pointer(&bs[0])) - if sliceSize > C.sizeof_ulong { - return value - } - - // truncate the value to the # of bits present in the byte slice since - // the unsafe pointer will always grab/convert ULONG # of bytes - var mask uint - for i := 0; i < sliceSize; i++ { - mask |= 0xff << uint(i * 8) + const uint64Sz = 8 + sz := len(bs) + if sz < uint64Sz { + placeholder := make([]byte, uint64Sz) + copy(placeholder, bs) + bs = placeholder } - return value & mask + nn := binary.LittleEndian.Uint64(bs) + n = uint(nn) + return n } func concat(slices ...[]byte) []byte { diff --git a/common_test.go b/common_test.go index ef08e4b..0ed86a0 100644 --- a/common_test.go +++ b/common_test.go @@ -1,6 +1,7 @@ package crypto11 import ( + "fmt" "testing" ) @@ -10,6 +11,11 @@ func TestULongMasking(t *testing.T) { // Build an slice that is longer than the size of a ulong extraLongSlice := append(ulongSlice, ulongSlice...) + expected := "AABBCCDD00112233AABBCCDD00112233" + actual := fmt.Sprintf("%X", string(extraLongSlice)) + if expected != actual { + t.Errorf("expected %s != %s", expected, actual) + } tests := []struct { slice []uint8 @@ -30,7 +36,7 @@ func TestULongMasking(t *testing.T) { for _, test := range tests { got := bytesToUlong(test.slice) if test.expected != got { - t.Errorf("conversion failed: 0x%X != 0x%X", test.expected, got) + t.Errorf("conversion failed: expected 0x%X != 0x%X", test.expected, got) } } }