Skip to content

Commit

Permalink
cert: Add issuer certificate (#2942)
Browse files Browse the repository at this point in the history
This PR adds the issuer certificate with parsing and validation.

contributes to #2853
  • Loading branch information
oncilla authored Jul 30, 2019
1 parent fbcef92 commit 1ba9a48
Show file tree
Hide file tree
Showing 5 changed files with 473 additions and 0 deletions.
3 changes: 3 additions & 0 deletions go/lib/scrypto/cert/v2/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
srcs = [
"as.go",
"base.go",
"issuer.go",
],
importpath = "github.com/scionproto/scion/go/lib/scrypto/cert/v2",
visibility = ["//visibility:public"],
Expand All @@ -22,6 +23,8 @@ go_test(
"as_test.go",
"base_json_test.go",
"base_test.go",
"issuer_json_test.go",
"issuer_test.go",
],
embed = [":go_default_library"],
deps = [
Expand Down
11 changes: 11 additions & 0 deletions go/lib/scrypto/cert/v2/as_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/scionproto/scion/go/lib/addr"
"github.com/scionproto/scion/go/lib/scrypto"
"github.com/scionproto/scion/go/lib/scrypto/cert/v2"
)
Expand Down Expand Up @@ -51,6 +52,16 @@ func TestASUnmarshalJSON(t *testing.T) {
}
},
},
"With optional distribution points": {
baseTest: baseTest{
Modify: func(g *genCert) {
(*g.OptDistPoints) = []addr.IA{ia210}
},
},
ModifyExpected: func(c *cert.AS) {
c.OptionalDistributionPoints = []addr.IA{ia210}
},
},
"Invalid CertificateType": {
baseTest: baseTest{
Modify: func(g *genCert) {
Expand Down
136 changes: 136 additions & 0 deletions go/lib/scrypto/cert/v2/issuer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2019 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cert

import (
"bytes"
"encoding/json"
"errors"

"github.com/scionproto/scion/go/lib/common"
"github.com/scionproto/scion/go/lib/scrypto"
)

var (
// ErrIssuerTRCVersionNotSet indicates the issuer TRC version is not set.
ErrIssuerTRCVersionNotSet = errors.New("issuer TRC version not set")
)

// Issuer is the Issuer certificate.
type Issuer struct {
Base
// Issuer holds the TRC Version. Since the issuer certificate is
// self-signed, the issuing AS in the TRC is the same as the subject of this
// certificate.
Issuer IssuerTRC `json:"Issuer"`
// CertificateType ensures the correct certificate type when marshalling.
CertificateType TypeIssuer `json:"CertificateType"`
}

// Validate checks that the certificate is in a valid format.
func (c *Issuer) Validate() error {
if err := c.Base.Validate(); err != nil {
return err
}
if err := c.validateKeys(true); err != nil {
return err
}
return nil
}

// UnmarshalJSON checks that all fields are set.
func (c *Issuer) UnmarshalJSON(b []byte) error {
var cAlias issuerAlias
dec := json.NewDecoder(bytes.NewReader(b))
dec.DisallowUnknownFields()
if err := dec.Decode(&cAlias); err != nil {
return err
}
if err := cAlias.checkAllSet(); err != nil {
return err
}
*c = Issuer{
Base: cAlias.Base,
Issuer: *cAlias.Issuer,
CertificateType: *cAlias.CertificateType,
}
return nil
}

type issuerAlias struct {
Base
Issuer *IssuerTRC `json:"Issuer"`
CertificateType *TypeIssuer `json:"CertificateType"`
}

func (c *issuerAlias) checkAllSet() error {
if err := c.Base.checkAllSet(); err != nil {
return err
}
switch {
case c.Issuer == nil:
return ErrIssuerNotSet
case c.CertificateType == nil:
return ErrCertificateTypeNotSet
}
return nil
}

// issuerTRCAlias is necessary to avoid an infinite recursion when unmarshalling.
type issuerTRCAlias IssuerTRC

// IssuerTRC identifies the TRC that authenticates the issuer certificate. The
// issuer certificate is self-signed, thus, the issuing AS and TRC ISD are
// implied by the subject.
type IssuerTRC struct {
// TRCVersion is the version of the issuing TRC.
TRCVersion scrypto.Version `json:"TRCVersion"`
}

// UnmarshalJSON checks that all fields are set.
func (i *IssuerTRC) UnmarshalJSON(b []byte) error {
dec := json.NewDecoder(bytes.NewReader(b))
dec.DisallowUnknownFields()
if err := dec.Decode((*issuerTRCAlias)(i)); err != nil {
return err
}
return i.checkAllSet()
}

func (i *IssuerTRC) checkAllSet() error {
if i.TRCVersion == 0 {
return ErrIssuerTRCVersionNotSet
}
return nil
}

const TypeIssuerJSON = "Issuer"

// TypeIssuer indicates an AS certificate.
type TypeIssuer struct{}

// UnmarshalText checks that the certificate type matches.
func (TypeIssuer) UnmarshalText(b []byte) error {
if TypeIssuerJSON != string(b) {
return common.NewBasicError(InvalidCertificateType, nil,
"expected", TypeIssuerJSON, "actual", string(b))
}
return nil
}

// MarshalText returns the AS certificate type.
func (TypeIssuer) MarshalText() ([]byte, error) {
return []byte(TypeIssuerJSON), nil
}
Loading

0 comments on commit 1ba9a48

Please sign in to comment.