Skip to content

Commit 1a3bc1c

Browse files
cryptobyte: support 64 bit object identifiers
asn1.ObjectIdentifier is a slice of ints and asn1.Marshal can serialize int values greater than 2^31-1 on 64 bit platforms. This change updates ReadASN1ObjectIdentifier to support greater int values on 64 bit platforms. For golang/go#58821
1 parent 776e461 commit 1a3bc1c

File tree

4 files changed

+87
-30
lines changed

4 files changed

+87
-30
lines changed

cryptobyte/asn1.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package cryptobyte
77
import (
88
encoding_asn1 "encoding/asn1"
99
"fmt"
10+
"math"
1011
"math/big"
1112
"reflect"
1213
"time"
@@ -421,12 +422,7 @@ func (s *String) ReadASN1Enum(out *int) bool {
421422
func (s *String) readBase128Int(out *int) bool {
422423
ret := 0
423424
for i := 0; len(*s) > 0; i++ {
424-
if i == 5 {
425-
return false
426-
}
427-
// Avoid overflowing int on a 32-bit platform.
428-
// We don't want different behavior based on the architecture.
429-
if ret >= 1<<(31-7) {
425+
if ret > math.MaxInt>>7 {
430426
return false
431427
}
432428
ret <<= 7

cryptobyte/asn1_32bit_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2023 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+
//go:build 386 || arm || mips || mipsle
6+
7+
package cryptobyte
8+
9+
import (
10+
"fmt"
11+
"testing"
12+
)
13+
14+
func TestASN1ObjectIdentifier32bit(t *testing.T) {
15+
testData := []readASN1ObjectIdentifierTest{
16+
{[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31
17+
}
18+
19+
for i, test := range testData {
20+
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
21+
testASN1ObjectIdentifier(t, test)
22+
})
23+
}
24+
}

cryptobyte/asn1_64bit_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2023 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+
//go:build !(386 || arm || mips || mipsle)
6+
7+
package cryptobyte
8+
9+
import (
10+
"fmt"
11+
"testing"
12+
)
13+
14+
func TestASN1ObjectIdentifier64bit(t *testing.T) {
15+
testData := []readASN1ObjectIdentifierTest{
16+
{[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, true, []int{2, 5, 2, 2147483648}}, // 2**31
17+
{[]byte{6, 11, 0x2a, 0x24, 0xcb, 0x89, 0x90, 0x82, 0x1e, 0x03, 0x01, 0x01, 0x01}, true, []int{1, 2, 36, 20151795998, 3, 1, 1, 1}}, // https://github.com/golang/go/issues/58821
18+
{[]byte{6, 11, 0x55, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 9223372036854775807}}, // 2**63-1
19+
{[]byte{0, 12, 0x55, 0x02, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**63
20+
}
21+
22+
for i, test := range testData {
23+
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
24+
testASN1ObjectIdentifier(t, test)
25+
})
26+
}
27+
}

cryptobyte/asn1_test.go

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package cryptobyte
77
import (
88
"bytes"
99
encoding_asn1 "encoding/asn1"
10+
"fmt"
1011
"math/big"
1112
"reflect"
1213
"testing"
@@ -259,12 +260,14 @@ func TestReadASN1IntegerInvalid(t *testing.T) {
259260
}
260261
}
261262

263+
type readASN1ObjectIdentifierTest struct {
264+
in []byte
265+
ok bool
266+
out []int
267+
}
268+
262269
func TestASN1ObjectIdentifier(t *testing.T) {
263-
testData := []struct {
264-
in []byte
265-
ok bool
266-
out []int
267-
}{
270+
testData := []readASN1ObjectIdentifierTest{
268271
{[]byte{}, false, []int{}},
269272
{[]byte{6, 0}, false, []int{}},
270273
{[]byte{5, 1, 85}, false, []int{2, 5}},
@@ -275,29 +278,36 @@ func TestASN1ObjectIdentifier(t *testing.T) {
275278
{[]byte{6, 7, 85, 0x02, 0xc0, 0x80, 0x80, 0x80, 0x80}, false, []int{}},
276279
{[]byte{6, 7, 85, 0x02, 0x85, 0xc7, 0xcc, 0xfb, 0x01}, true, []int{2, 5, 2, 1492336001}},
277280
{[]byte{6, 7, 0x55, 0x02, 0x87, 0xff, 0xff, 0xff, 0x7f}, true, []int{2, 5, 2, 2147483647}}, // 2**31-1
278-
{[]byte{6, 7, 0x55, 0x02, 0x88, 0x80, 0x80, 0x80, 0x00}, false, []int{}}, // 2**31
279281
}
280282

281283
for i, test := range testData {
282-
in := String(test.in)
283-
var out encoding_asn1.ObjectIdentifier
284-
ok := in.ReadASN1ObjectIdentifier(&out)
285-
if ok != test.ok || ok && !out.Equal(test.out) {
286-
t.Errorf("#%d: in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", i, ok, test.ok, out, test.out)
287-
continue
288-
}
284+
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
285+
testASN1ObjectIdentifier(t, test)
286+
})
287+
}
288+
}
289289

290-
var b Builder
291-
b.AddASN1ObjectIdentifier(out)
292-
result, err := b.Bytes()
293-
if builderOk := err == nil; test.ok != builderOk {
294-
t.Errorf("#%d: error from Builder.Bytes: %s", i, err)
295-
continue
296-
}
297-
if test.ok && !bytes.Equal(result, test.in) {
298-
t.Errorf("#%d: reserialisation didn't match, got %x, want %x", i, result, test.in)
299-
continue
300-
}
290+
func testASN1ObjectIdentifier(t *testing.T, test readASN1ObjectIdentifierTest) {
291+
t.Helper()
292+
293+
in := String(test.in)
294+
var out encoding_asn1.ObjectIdentifier
295+
ok := in.ReadASN1ObjectIdentifier(&out)
296+
if ok != test.ok || ok && !out.Equal(test.out) {
297+
t.Errorf("in.ReadASN1ObjectIdentifier() = %v, want %v; out = %v, want %v", ok, test.ok, out, test.out)
298+
return
299+
}
300+
301+
var b Builder
302+
b.AddASN1ObjectIdentifier(out)
303+
result, err := b.Bytes()
304+
if builderOk := err == nil; test.ok != builderOk {
305+
t.Errorf("error from Builder.Bytes: %s", err)
306+
return
307+
}
308+
if test.ok && !bytes.Equal(result, test.in) {
309+
t.Errorf("reserialisation didn't match, got %x, want %x", result, test.in)
310+
return
301311
}
302312
}
303313

0 commit comments

Comments
 (0)