aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--x509util/x509util.go7
-rw-r--r--x509util/x509util_test.go112
2 files changed, 100 insertions, 19 deletions
diff --git a/x509util/x509util.go b/x509util/x509util.go
index f95b136..c3ebd4b 100644
--- a/x509util/x509util.go
+++ b/x509util/x509util.go
@@ -104,8 +104,11 @@ func NewEd25519PrivateKey(data []byte) (ed25519.PrivateKey, error) {
// the remaining ones as its intermediate CertPool.
func ParseDerChain(chain [][]byte) (*x509.Certificate, *x509.CertPool, error) {
certificates, err := ParseDerList(chain)
- if err != nil || len(certificates) == 0 {
- return nil, nil, err // TODO: don't think the len check works now..
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(certificates) == 0 {
+ return nil, nil, fmt.Errorf("empty certificate chain")
}
intermediatePool := x509.NewCertPool()
for _, certificate := range certificates[1:] {
diff --git a/x509util/x509util_test.go b/x509util/x509util_test.go
index 538ef45..298293b 100644
--- a/x509util/x509util_test.go
+++ b/x509util/x509util_test.go
@@ -5,6 +5,8 @@ import (
"fmt"
"testing"
+ "crypto/x509"
+
"github.com/system-transparency/stfe/x509util/testdata"
)
@@ -150,8 +152,66 @@ func TestNewCertPool(t *testing.T) {
}
}
-// TODO: TestParseDerChain
func TestParseDerChain(t *testing.T) {
+ for _, table := range []struct {
+ description string
+ chain [][]byte
+ wantErr bool
+ }{
+ {
+ description: "invalid chain: empty",
+ wantErr: true,
+ },
+ {
+ description: "invalid chain: first certificate: byte is missing",
+ chain: [][]byte{
+ mustMakeDerList(t, testdata.IntermediateChain)[0][1:],
+ mustMakeDerList(t, testdata.IntermediateChain)[1],
+ },
+ wantErr: true,
+ },
+ {
+ description: "valid chain: size 1",
+ chain: mustMakeDerList(t, testdata.EndEntityCertificate),
+ },
+ {
+ description: "valid chain: size 2",
+ chain: mustMakeDerList(t, testdata.IntermediateChain),
+ },
+ {
+ description: "valid chain: size 3",
+ chain: mustMakeDerList(t, testdata.RootChain),
+ },
+ } {
+ cert, pool, err := ParseDerChain(table.chain)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error=%v but wanted %v in test %q: %v", got, want, table.description, err)
+ }
+ if err != nil {
+ continue
+ }
+
+ if got, want := cert.Raw, table.chain[0]; !bytes.Equal(got, want) {
+ t.Errorf("got end-entity certificate %X but wanted %X in test %q", got, want, table.description)
+ }
+ if got, want := len(pool.Subjects()), len(table.chain)-1; got != want {
+ t.Errorf("got %d intermediates but wanted %d in test %q", got, want, table.description)
+ continue
+ }
+ for _, der := range table.chain[1:] {
+ want := mustMakeCertificate(t, der).RawSubject
+ ok := false
+ for _, got := range pool.Subjects() {
+ if bytes.Equal(got, want) {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ t.Errorf("want subject %X but found no match in test %q", want, table.description)
+ }
+ }
+ }
}
func TestParseDerList(t *testing.T) {
@@ -161,9 +221,18 @@ func TestParseDerList(t *testing.T) {
wantErr bool
}{
{
- description: "invalid certificate: first byte is missing",
+ description: "invalid certificate: first certificate: byte is missing",
+ list: [][]byte{
+ mustMakeDerList(t, testdata.IntermediateChain)[0][1:],
+ mustMakeDerList(t, testdata.IntermediateChain)[1],
+ },
+ wantErr: true,
+ },
+ {
+ description: "invalid certificate: second certificate: byte is missing",
list: [][]byte{
- mustMakeDerList(t, testdata.EndEntityCertificate)[0][1:],
+ mustMakeDerList(t, testdata.IntermediateChain)[0],
+ mustMakeDerList(t, testdata.IntermediateChain)[1][1:],
},
wantErr: true,
},
@@ -203,20 +272,6 @@ func TestParseDerList(t *testing.T) {
}
}
-// mustMakeDerList must create a list of DER-encoded certificates from PEM
-func mustMakeDerList(t *testing.T, pem []byte) [][]byte {
- certs, err := NewCertificateList(pem)
- if err != nil {
- t.Fatalf("must parse pem-encoded certificates: %v", err)
- }
-
- list := make([][]byte, 0, len(certs))
- for _, cert := range certs {
- list = append(list, cert.Raw)
- }
- return list
-}
-
func TestVerifyChain(t *testing.T) {
for _, table := range []struct {
description string
@@ -252,3 +307,26 @@ func TestVerifyChain(t *testing.T) {
}
}
}
+
+// mustMakeDerList must parse a PEM-encoded list of certificates to DER
+func mustMakeDerList(t *testing.T, pem []byte) [][]byte {
+ certs, err := NewCertificateList(pem)
+ if err != nil {
+ t.Fatalf("must parse pem-encoded certificates: %v", err)
+ }
+
+ list := make([][]byte, 0, len(certs))
+ for _, cert := range certs {
+ list = append(list, cert.Raw)
+ }
+ return list
+}
+
+// mustMakeCertificate must parse a DER-encoded certificate
+func mustMakeCertificate(t *testing.T, der []byte) *x509.Certificate {
+ cert, err := x509.ParseCertificate(der)
+ if err != nil {
+ t.Fatalf("must parsse der-encoded certificate: %v", err)
+ }
+ return cert
+}