Skip to content

Commit

Permalink
scion-pki: allow referencing predecessor certificates in payload (#4625)
Browse files Browse the repository at this point in the history
When creating a TRC update, support referencing the predecessor
certificates. This simplifies the TRC ceremony, as the already included
certificates do not need to be redistributed in case they do not change.
  • Loading branch information
oncilla authored Sep 18, 2024
1 parent a83a906 commit 296ec95
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 7 deletions.
20 changes: 19 additions & 1 deletion scion-pki/conf/trc.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package conf
import (
"crypto/x509"
"path/filepath"
"strconv"
"strings"

"github.com/scionproto/scion/pkg/addr"
Expand Down Expand Up @@ -59,12 +60,29 @@ func LoadTRC(file string) (TRC, error) {
}

// Certificates returns the specified certificates.
func (cfg *TRC) Certificates() ([]*x509.Certificate, error) {
func (cfg *TRC) Certificates(pred *cppki.TRC) ([]*x509.Certificate, error) {
if len(cfg.CertificateFiles) == 0 {
return nil, serrors.New("no cert_files specified")
}

certs := make([]*x509.Certificate, 0, len(cfg.CertificateFiles))
for _, certFile := range cfg.CertificateFiles {

if raw, ok := strings.CutPrefix(certFile, "predecessor:"); ok {
if pred == nil {
return nil, serrors.New("predecessor certificate requested on base TRC")
}
idx, err := strconv.Atoi(raw)
if err != nil {
return nil, serrors.Wrap("parsing predecessor index", err, "input", raw)
}
if idx < 0 || idx >= len(pred.Certificates) {
return nil, serrors.New("predecessor index out of bounds", "index", idx)
}
certs = append(certs, pred.Certificates[idx])
continue
}

if !strings.HasPrefix(certFile, "/") {
certFile = filepath.Join(cfg.relPath, certFile)
}
Expand Down
12 changes: 11 additions & 1 deletion scion-pki/conf/trc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,21 @@ func TestTRCCertificates(t *testing.T) {
prepareCfg func(*conf.TRC)
errMsg string
expectedCrts []*x509.Certificate
pred *cppki.TRC
}{
"valid": {
prepareCfg: func(_ *conf.TRC) {},
expectedCrts: []*x509.Certificate{rVoting, sVoting},
},
"load from predecessor": {
prepareCfg: func(cfg *conf.TRC) {
cfg.CertificateFiles[0] = "predecessor:4"
},
expectedCrts: []*x509.Certificate{rVoting, sVoting},
pred: &cppki.TRC{
Certificates: []*x509.Certificate{4: rVoting},
},
},
"file not found": {
prepareCfg: func(cfg *conf.TRC) { cfg.CertificateFiles = []string{"notfound"} },
errMsg: "no such file or directory",
Expand All @@ -128,7 +138,7 @@ func TestTRCCertificates(t *testing.T) {
t.Run(name, func(t *testing.T) {
cfg := createTRC(t)
tc.prepareCfg(cfg)
crts, err := cfg.Certificates()
crts, err := cfg.Certificates(tc.pred)
if tc.errMsg != "" {
assert.Error(t, err)
assert.Contains(t, err.Error(), tc.errMsg)
Expand Down
2 changes: 1 addition & 1 deletion scion-pki/testcrypto/testcrypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ func createTRCs(cfg config) error {
CertificateFiles: certFiles[isd],
}
sort.Strings(trcConf.CertificateFiles)
trc, err := trcs.CreatePayload(trcConf)
trc, err := trcs.CreatePayload(trcConf, nil)
if err != nil {
return serrors.Wrap("creating TRC payload", err, "isd", isd)
}
Expand Down
2 changes: 1 addition & 1 deletion scion-pki/trcs/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ To inspect the created asn.1 file you can use the openssl tool::
return err
}
prepareCfg(&cfg, pred)
trc, err := CreatePayload(cfg)
trc, err := CreatePayload(cfg, pred)
if err != nil {
return serrors.Wrap("failed to marshal TRC", err)
}
Expand Down
4 changes: 2 additions & 2 deletions scion-pki/trcs/toasn.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (

// CreatePayload creates the ASN.1 payload for the TRC from the given
// configuration.
func CreatePayload(cfg conf.TRC) (*cppki.TRC, error) {
certs, err := cfg.Certificates()
func CreatePayload(cfg conf.TRC, pred *cppki.TRC) (*cppki.TRC, error) {
certs, err := cfg.Certificates(pred)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion scion-pki/trcs/toasn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
func TestMarshalPayload(t *testing.T) {
cfg, err := conf.LoadTRC("testdata/admin/ISD1-B1-S1.toml")
require.NoError(t, err)
trc, err := CreatePayload(cfg)
trc, err := CreatePayload(cfg, nil)
require.NoError(t, err)
raw, err := trc.Encode()
require.NoError(t, err)
Expand Down

0 comments on commit 296ec95

Please sign in to comment.