Skip to content

Commit

Permalink
scion-pki: add --isd flag to trc verify command
Browse files Browse the repository at this point in the history
Add a `--isd` flag to the `trc verify` command.

This optional flag enables checking the ISD number the TRC chain that is being verified.
The new flag simplifies CLI interactions for tools that want to validate that a TRC chain is for a specific ISD.

Closes #4171

GitOrigin-RevId: 0a1de869114761795ebe465c37990f0f170a4df9
  • Loading branch information
FR4NK-W authored and oncilla committed Mar 26, 2022
1 parent 1940c15 commit 03034e3
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 9 deletions.
9 changes: 9 additions & 0 deletions pkg/private/xtest/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ func CopyDir(t testing.TB, from, to string) {
require.NoError(t, err, string(out))
}

// CopyFile copies the file.
func CopyFile(t testing.TB, src, dst string) {
t.Helper()

raw, err := os.ReadFile(src)
require.NoError(t, err)
require.NoError(t, os.WriteFile(dst, raw, 0666))
}

// FailOnErr causes t to exit with a fatal error if err is non-nil.
func FailOnErr(t testing.TB, err error, desc ...string) {
t.Helper()
Expand Down
2 changes: 1 addition & 1 deletion scion-pki/testcrypto/testcrypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestCmd(t *testing.T) {
func checkISD(t *testing.T, outDir string, isd addr.ISD) {
isdDir := filepath.Join(outDir, fmt.Sprintf("ISD%d", isd))
trcFile := filepath.Join(isdDir, "trcs", fmt.Sprintf("ISD%d-B1-S1.trc", isd))
assert.NoError(t, trcs.RunVerify([]string{trcFile}, trcFile))
assert.NoError(t, trcs.RunVerify([]string{trcFile}, trcFile, 0))
}

func checkAS(t *testing.T, outDir string, ia addr.IA) {
Expand Down
26 changes: 19 additions & 7 deletions scion-pki/trcs/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
func newVerify(pather command.Pather) *cobra.Command {
var flags struct {
anchor string
isd uint16
}

cmd := &cobra.Command{
Expand All @@ -48,21 +49,24 @@ The anchor can either be a collection of trusted certificates bundled in a PEM
file, or a trusted TRC. TRC update chains that start with a base TRC can be
verified with either type of anchor. TRC update chains that start with a
non-base TRC must have a TRC as anchor.
With the optional flag --isd, the ID of the ISD for which the TRC claims to be
the root of trust can be matched against an expected value.
`,
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
return RunVerify(args, flags.anchor)
return RunVerify(args, flags.anchor, addr.ISD(flags.isd))
},
}

cmd.Flags().StringVarP(&flags.anchor, "anchor", "a", "", "trust anchor (required)")
cmd.Flags().Uint16Var(&flags.isd, "isd", 0, "ISD identifier")
cmd.MarkFlagRequired("anchor")
return cmd
}

// RunVerify runs verification of the TRC files from the given anchor.
func RunVerify(files []string, anchor string) error {
func RunVerify(files []string, anchor string, isd addr.ISD) error {
var trcs []cppki.SignedTRC
for _, name := range files {
dec, err := DecodeFromFile(name)
Expand All @@ -71,19 +75,27 @@ func RunVerify(files []string, anchor string) error {
}
trcs = append(trcs, dec)
}
isd, base := trcs[0].TRC.ID.ISD, trcs[0].TRC.ID.Base
if len(trcs) == 0 {
return serrors.New("TRC verify requires at least one TRC to verify")
}
someISD, someBase := trcs[0].TRC.ID.ISD, trcs[0].TRC.ID.Base
for _, dec := range trcs {
if isd != dec.TRC.ID.ISD {
return serrors.New("multiple ISDs", "isds", []addr.ISD{isd, dec.TRC.ID.ISD})
if someISD != dec.TRC.ID.ISD {
return serrors.New("multiple ISDs", "isds", []addr.ISD{someISD, dec.TRC.ID.ISD})
}
if base != dec.TRC.ID.Base {
if someBase != dec.TRC.ID.Base {
return serrors.New("multiple base versions", "bases", []scrypto.Version{
base, dec.TRC.ID.Base})
someBase, dec.TRC.ID.Base})
}
}
sort.Slice(trcs, func(i, j int) bool {
return trcs[i].TRC.ID.Serial < trcs[j].TRC.ID.Serial
})
if anchorISD := trcs[0].TRC.ID.ISD; isd != 0 && anchorISD != isd {
return serrors.New("TRC anchor ISD does not match the requested ISD ID",
"expected", isd,
"actual", anchorISD)
}
serials := []scrypto.Version{trcs[0].TRC.ID.Serial}
for i := 1; i < len(trcs); i++ {
serials = append(serials, trcs[i].TRC.ID.Serial)
Expand Down
41 changes: 40 additions & 1 deletion scion-pki/trcs/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/stretchr/testify/require"

"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/private/xtest"
)

Expand All @@ -32,18 +33,21 @@ func TestVerify(t *testing.T) {
testCases := map[string]struct {
Files []string
Anchor string
ISD addr.ISD
Prepare func(t *testing.T)
ErrAssertion require.ErrorAssertionFunc
}{
"base-trc-anchor": {
Files: []string{"./testdata/admin/ISD1-B1-S1.trc"},
Anchor: "./testdata/admin/ISD1-B1-S1.trc",
ISD: 0,
Prepare: func(*testing.T) {},
ErrAssertion: require.NoError,
},
"base-bundle-anchor": {
Files: []string{"./testdata/admin/ISD1-B1-S1.trc"},
Anchor: filepath.Join(dir, "base.pem"),
ISD: 0,
Prepare: func(*testing.T) {
out := filepath.Join(dir, "base.pem")
require.NoError(t, runExtractCertificates("./testdata/admin/ISD1-B1-S1.trc", out))
Expand All @@ -53,6 +57,7 @@ func TestVerify(t *testing.T) {
"base-bundle-missing": {
Files: []string{"./testdata/admin/ISD1-B1-S1.trc"},
Anchor: filepath.Join(dir, "base-missing.pem"),
ISD: 0,
Prepare: func(*testing.T) {
signed, err := DecodeFromFile("./testdata/admin/ISD1-B1-S1.trc")
require.NoError(t, err)
Expand All @@ -64,6 +69,7 @@ func TestVerify(t *testing.T) {
"base-invalid-signature": {
Files: []string{filepath.Join(dir, "base-invalid-signature.der")},
Anchor: "./testdata/admin/ISD1-B1-S1.trc",
ISD: 0,
Prepare: func(*testing.T) {
signed, err := DecodeFromFile("./testdata/admin/ISD1-B1-S1.trc")
require.NoError(t, err)
Expand All @@ -77,11 +83,44 @@ func TestVerify(t *testing.T) {
},
ErrAssertion: require.Error,
},
"base-ISD-check": {
Files: []string{"./testdata/admin/ISD1-B1-S1.trc"},
Anchor: "./testdata/admin/ISD1-B1-S1.trc",
ISD: 1,
Prepare: func(*testing.T) {},
ErrAssertion: require.NoError,
},
"base-verify-ISD": {
Files: []string{filepath.Join(dir, "non-descript.trc")},
Anchor: filepath.Join(dir, "non-descript.trc"),
ISD: 1,
Prepare: func(*testing.T) {
xtest.CopyFile(
t,
"testdata/admin/ISD1-B1-S1.trc",
filepath.Join(dir, "non-descript.trc"),
)
},
ErrAssertion: require.NoError,
},
"base-ISD-mismatch": {
Files: []string{filepath.Join(dir, "non-descript-2dashes.trc")},
Anchor: filepath.Join(dir, "non-descript-linked.trc"),
ISD: 10,
Prepare: func(*testing.T) {
xtest.CopyFile(
t,
"testdata/admin/ISD1-B1-S1.trc",
filepath.Join(dir, "non-descript-2dashes.trc"),
)
},
ErrAssertion: require.Error,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
tc.Prepare(t)
err := RunVerify(tc.Files, tc.Anchor)
err := RunVerify(tc.Files, tc.Anchor, tc.ISD)
tc.ErrAssertion(t, err)
})
}
Expand Down

0 comments on commit 03034e3

Please sign in to comment.