diff --git a/comid/measurement.go b/comid/measurement.go index 1977735..c64909f 100644 --- a/comid/measurement.go +++ b/comid/measurement.go @@ -424,6 +424,7 @@ func (o Mval) MarshalJSON() ([]byte, error) { } func (o Mval) Valid() error { + // Check if no measurement values are set if o.Ver == nil && o.SVN == nil && o.Digests == nil && @@ -439,28 +440,47 @@ func (o Mval) Valid() error { return fmt.Errorf("no measurement value set") } + // Validate Version if o.Ver != nil { if err := o.Ver.Valid(); err != nil { return err } } + // Validate Digests if o.Digests != nil { if err := o.Digests.Valid(); err != nil { return err } } + // Validate Flags if o.Flags != nil { if err := o.Flags.Valid(); err != nil { return err } } - // raw value and mask have no specific semantics + // Validate MAC Address + if o.MACAddr != nil { + macLen := len(*o.MACAddr) + if macLen != 6 && macLen != 8 { // MAC address must be either 6 or 8 bytes + return fmt.Errorf("invalid MAC address length: expected 6 or 8 bytes, got %d", macLen) + } + } + + // Validate IP Address + if o.IPAddr != nil { + ip := *o.IPAddr + // Must be valid IPv4 or IPv6 (i.e., .To4() != nil or .To16() != nil) + if ip.To4() == nil && ip.To16() == nil { + return fmt.Errorf("invalid IP address: %s", ip.String()) + } + } - // TODO(tho) MAC addr & friends (see https://github.com/veraison/corim/issues/18) + // raw value and raw-value-mask have no specific semantics here + // Validate extensions (custom logic implemented in validMval()) return o.Extensions.validMval(&o) } diff --git a/comid/measurement_test.go b/comid/measurement_test.go index 078c7ee..45505ea 100644 --- a/comid/measurement_test.go +++ b/comid/measurement_test.go @@ -6,6 +6,7 @@ package comid import ( "crypto" "fmt" + "net" "testing" "github.com/stretchr/testify/assert" @@ -601,3 +602,99 @@ func TestMkey_UintMkey(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 7, ret) } + +func TestMval_Valid(t *testing.T) { + t.Run("No fields set", func(t *testing.T) { + mval := Mval{} + err := mval.Valid() + assert.EqualError(t, err, "no measurement value set") + }) + + t.Run("All fields nil except Ver, which is valid", func(t *testing.T) { + var scheme swid.VersionScheme + _ = scheme.SetCode(swid.VersionSchemeSemVer) + mval := Mval{ + Ver: &Version{ + Version: "1.0", + Scheme: scheme, + }, + } + err := mval.Valid() + assert.NoError(t, err) + }) + + // Test with valid 6-byte MAC + t.Run("MACAddr valid (6 bytes)", func(t *testing.T) { + mac := MACaddr([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) // EUI-48 + mval := Mval{MACAddr: &mac} + err := mval.Valid() + assert.NoError(t, err, "6-byte MAC should be valid") + }) + + // Test with valid 8-byte MAC + t.Run("MACAddr valid (8 bytes)", func(t *testing.T) { + mac := MACaddr([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}) // EUI-64 + mval := Mval{MACAddr: &mac} + err := mval.Valid() + assert.NoError(t, err, "8-byte MAC should be valid") + }) + + // Test with invalid MAC length + t.Run("MACAddr invalid (too many bytes)", func(t *testing.T) { + mac := MACaddr([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}) // 7 bytes + mval := Mval{MACAddr: &mac} + err := mval.Valid() + assert.EqualError(t, err, "invalid MAC address length: expected 6 or 8 bytes, got 7") + }) + + // Test with invalid MAC length + t.Run("MACAddr invalid (too few bytes)", func(t *testing.T) { + mac := MACaddr([]byte{0x01, 0x02, 0x03, 0x04}) // 4 bytes + mval := Mval{MACAddr: &mac} + err := mval.Valid() + assert.EqualError(t, err, "invalid MAC address length: expected 6 or 8 bytes, got 4") + }) + + t.Run("MACAddr valid (6 bytes)", func(t *testing.T) { + mac := MACaddr([]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) + mval := Mval{MACAddr: &mac} + err := mval.Valid() + assert.NoError(t, err) + }) + + t.Run("IPAddr valid (IPv4)", func(t *testing.T) { + ip := net.IPv4(192, 168, 1, 100) + mval := Mval{IPAddr: &ip} + err := mval.Valid() + assert.NoError(t, err) + }) + + t.Run("IPAddr valid (IPv6)", func(t *testing.T) { + ip := net.ParseIP("2001:db8::1") + mval := Mval{IPAddr: &ip} + err := mval.Valid() + assert.NoError(t, err) + }) + + t.Run("Digests valid", func(t *testing.T) { + ds := NewDigests() + _ = ds.AddDigest(swid.Sha256, []byte{0xAA, 0xBB}) + mval := Mval{ + Digests: ds, + } + err := mval.Valid() + assert.NoError(t, err) + }) + + t.Run("Extensions valid", func(t *testing.T) { + // Suppose we have some extension data that is considered valid + ext := Extensions{} + mval := Mval{ + Extensions: ext, + // Must also set one non-empty field to pass "no measurement value set" + Ver: &Version{Version: "1.0"}, + } + err := mval.Valid() + assert.NoError(t, err) + }) +}