yubikey_test.go

 1package pgp
 2
 3import (
 4	"strings"
 5	"testing"
 6)
 7
 8// TestParseASN1Signature_TruncatedDoesNotPanic covers the bounds-check path
 9// added for #613. Each input would have panicked in the original parser
10// with "index out of range"; here we expect a typed error instead.
11func TestParseASN1Signature_TruncatedDoesNotPanic(t *testing.T) {
12	cases := []struct {
13		name    string
14		der     []byte
15		wantErr string
16	}{
17		{
18			// Length byte declares 0x10 bytes of R but only 1 byte follows.
19			name:    "R length overruns buffer",
20			der:     []byte{0x30, 0x06, 0x02, 0x10, 0xAA, 0x00},
21			wantErr: "R length overflow",
22		},
23		{
24			// Length byte declares 0x10 bytes of S but only 1 byte follows.
25			name:    "S length overruns buffer",
26			der:     []byte{0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x10, 0xAA},
27			wantErr: "S length overflow",
28		},
29		{
30			// Valid R, then no S block at all.
31			name:    "missing S after R",
32			der:     []byte{0x30, 0x06, 0x02, 0x01, 0x01, 0x00},
33			wantErr: "expected INTEGER tag for S",
34		},
35	}
36
37	for _, tc := range cases {
38		tc := tc
39		t.Run(tc.name, func(t *testing.T) {
40			// The test must not panic: the fix replaces panics with errors.
41			defer func() {
42				if r := recover(); r != nil {
43					t.Fatalf("parseASN1Signature panicked: %v", r)
44				}
45			}()
46			_, _, err := parseASN1Signature(tc.der)
47			if err == nil {
48				t.Fatalf("want error, got nil")
49			}
50			if !strings.Contains(err.Error(), tc.wantErr) {
51				t.Fatalf("error = %q, want it to mention %q", err.Error(), tc.wantErr)
52			}
53		})
54	}
55}
56
57// TestParseASN1Signature_WellFormed guards against regressions in the
58// happy path: a minimal SEQUENCE { INTEGER, INTEGER } must still decode
59// to the original r and s bytes.
60func TestParseASN1Signature_WellFormed(t *testing.T) {
61	// SEQUENCE (6 bytes) { INTEGER 0x01, INTEGER 0x02 }
62	der := []byte{0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}
63
64	r, s, err := parseASN1Signature(der)
65	if err != nil {
66		t.Fatalf("unexpected error: %v", err)
67	}
68	if len(r) != 1 || r[0] != 0x01 {
69		t.Errorf("r = %x, want 01", r)
70	}
71	if len(s) != 1 || s[0] != 0x02 {
72		t.Errorf("s = %x, want 02", s)
73	}
74}