Skip to content

Commit

Permalink
add test, support creating certificates with new OID type
Browse files Browse the repository at this point in the history
Change-Id: Icc7b68161dca294e6524f6efb1c690b80b48f96e
  • Loading branch information
mateusz834 committed Aug 19, 2023
1 parent c531c36 commit 818cb93
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 7 deletions.
8 changes: 8 additions & 0 deletions src/crypto/x509/oid.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ func newOIDFromDER(der []byte) (OID, bool) {
return OID{der}, true
}

func mustNewOIDFromInts(ints []uint64) OID {
oid, err := OIDFromInts(ints)
if err != nil {
panic("crypto/x509: mustNewOIDFromInts: " + err.Error())
}
return oid
}

// OIDFromInts creates a new OID using ints, each integer is a separate component.
func OIDFromInts(oid []uint64) (OID, error) {
if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
Expand Down
27 changes: 20 additions & 7 deletions src/crypto/x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKe

if len(template.PolicyIdentifiers) > 0 &&
!oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
ret[n], err = marshalCertificatePolicies(template.PolicyIdentifiers)
ret[n], err = marshalCertificatePolicies(template.Policies, template.PolicyIdentifiers)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1368,14 +1368,27 @@ func marshalBasicConstraints(isCA bool, maxPathLen int, maxPathLenZero bool) (pk
return ext, err
}

func marshalCertificatePolicies(policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) {
func marshalCertificatePolicies(policies []OID, policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) {
ext := pkix.Extension{Id: oidExtensionCertificatePolicies}
policies := make([]policyInformation, len(policyIdentifiers))
for i, policy := range policyIdentifiers {
policies[i].Policy = policy
}

b := cryptobyte.NewBuilder(make([]byte, 0, 128))
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
for _, v := range policies {
child.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
child.AddASN1(cryptobyte_asn1.OBJECT_IDENTIFIER, func(child *cryptobyte.Builder) {
child.AddBytes(v.der)
})
})
}
for _, v := range policyIdentifiers {
child.AddASN1(cryptobyte_asn1.SEQUENCE, func(child *cryptobyte.Builder) {
child.AddASN1ObjectIdentifier(v)
})
}
})

var err error
ext.Value, err = asn1.Marshal(policies)
ext.Value, err = b.Bytes()
return ext, err
}

Expand Down
49 changes: 49 additions & 0 deletions src/crypto/x509/x509_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ import (
"fmt"
"internal/testenv"
"io"
"math"
"math/big"
"net"
"net/url"
"os/exec"
"reflect"
"runtime"
"slices"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -671,6 +673,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
URIs: []*url.URL{parseURI("https://foo.com/wibble#foo")},

PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
Policies: []OID{mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxUint32, math.MaxUint64})},
PermittedDNSDomains: []string{".example.com", "example.com"},
ExcludedDNSDomains: []string{"bar.example.com"},
PermittedIPRanges: []*net.IPNet{parseCIDR("192.168.1.1/16"), parseCIDR("1.2.3.4/8")},
Expand Down Expand Up @@ -3917,3 +3920,49 @@ func TestDuplicateAttributesCSR(t *testing.T) {
t.Fatal("ParseCertificateRequest should succeed when parsing CSR with duplicate attributes")
}
}

func TestCertificateOIDPolicies(t *testing.T) {
template := Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "Cert"},
NotBefore: time.Unix(1000, 0),
NotAfter: time.Unix(100000, 0),
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
Policies: []OID{
mustNewOIDFromInts([]uint64{1, 2, 3, 4, 5}),
mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxInt32}),
mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxUint32, math.MaxUint64}),
},
}

var expectPolicyIdentifiers = []asn1.ObjectIdentifier{
[]int{1, 2, 3, 4, 5},
[]int{1, 2, 3, math.MaxInt32},
[]int{1, 2, 3},
}

var expectPolicies = []OID{
mustNewOIDFromInts([]uint64{1, 2, 3, 4, 5}),
mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxInt32}),
mustNewOIDFromInts([]uint64{1, 2, 3, math.MaxUint32, math.MaxUint64}),
mustNewOIDFromInts([]uint64{1, 2, 3}),
}

certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey)
if err != nil {
t.Fatalf("CreateCertificate() unexpected error: %v", err)
}

cert, err := ParseCertificate(certDER)
if err != nil {
t.Fatalf("ParseCertificate() unexpected error: %v", err)
}

if !slices.EqualFunc(cert.PolicyIdentifiers, expectPolicyIdentifiers, slices.Equal[asn1.ObjectIdentifier]) {
t.Errorf("cert.PolicyIdentifiers = %v, want: %v", cert.PolicyIdentifiers, expectPolicyIdentifiers)
}

if !slices.EqualFunc(cert.Policies, expectPolicies, func(o1, o2 OID) bool { return o1.Equal(o2) }) {
t.Errorf("cert.Policies = %v, want: %v", cert.Policies, expectPolicies)
}
}

0 comments on commit 818cb93

Please sign in to comment.