From e7bee5681bcb7d3dc486c65dce0e58f76aa8e91d Mon Sep 17 00:00:00 2001 From: Junming Chen <25316415+Chapoly1305@users.noreply.github.com> Date: Wed, 3 Dec 2025 22:43:04 -0500 Subject: [PATCH] Add OtaChecksumType validation per Matter Spec R1.4.2 Validate that OtaChecksumType is within the allowed list [1, 7, 8, 10, 11, 12] per IANA Named Information Hash Algorithm Registry (RFC 6920) when OtaUrl is provided. These values correspond to hash algorithms with minimum 256-bit digest length: sha-256, sha-384, sha-512, sha3-256, sha3-384, sha3-512. --- x/model/types/errors.go | 7 ++ x/model/types/messages_model_version.go | 17 ++++ x/model/types/messages_model_version_test.go | 96 ++++++++++++++++++-- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/x/model/types/errors.go b/x/model/types/errors.go index 36771c8d5..2fdb81c59 100644 --- a/x/model/types/errors.go +++ b/x/model/types/errors.go @@ -29,6 +29,7 @@ var ( ErrModelDeletionCertified = errors.Register(ModuleName, 525, "model has a model version that has a compliance record and correcponding model can not be deleted") ErrFieldIsNotBase64Encoded = errors.Register(ModuleName, 526, "Field is not base64 encoded string") ErrEnhancedSetupFlowTCRevisionInvalid = errors.Register(ModuleName, 527, "enhanced setup flow TC revision invalid") + ErrOtaChecksumTypeInvalid = errors.Register(ModuleName, 528, "OTA checksum type is not valid") ) func NewErrModelAlreadyExists(vid interface{}, pid interface{}) error { @@ -149,3 +150,9 @@ func NewErrEnhancedSetupFlowTCRevisionInvalidIncrement(newEnhancedSetupFlowTCRev return errors.Wrapf(ErrEnhancedSetupFlowTCRevisionInvalid, "EnhancedSetupFlowTCRevision %v is not correctly incremented to %v", prevEnhancedSetupFlowTCRevision, newEnhancedSetupFlowTCRevision) } + +func NewErrOtaChecksumTypeInvalid(otaChecksumType int32) error { + return errors.Wrapf(ErrOtaChecksumTypeInvalid, + "OtaChecksumType %v is not valid. Must be one of [1, 7, 8, 10, 11, 12] per IANA Named Information Hash Algorithm Registry", + otaChecksumType) +} diff --git a/x/model/types/messages_model_version.go b/x/model/types/messages_model_version.go index 55afc74a8..cd46145a9 100644 --- a/x/model/types/messages_model_version.go +++ b/x/model/types/messages_model_version.go @@ -80,6 +80,19 @@ func (msg *MsgCreateModelVersion) GetSignBytes() []byte { return sdk.MustSortJSON(bz) } +var ValidOtaChecksumTypes = map[int32]bool{ + 1: true, // sha-256 + 7: true, // sha-384 + 8: true, // sha-512 + 10: true, // sha3-256 + 11: true, // sha3-384 + 12: true, // sha3-512 +} + +func IsValidOtaChecksumType(checksumType int32) bool { + return ValidOtaChecksumTypes[checksumType] +} + func (msg *MsgCreateModelVersion) ValidateBasic() error { _, err := sdk.AccAddressFromBech32(msg.Creator) if err != nil { @@ -91,6 +104,10 @@ func (msg *MsgCreateModelVersion) ValidateBasic() error { return NewErrOtaChecksumIsNotBase64Encoded(msg.OtaChecksum) } + if msg.OtaUrl != "" && !IsValidOtaChecksumType(msg.OtaChecksumType) { + return NewErrOtaChecksumTypeInvalid(msg.OtaChecksumType) + } + err = validator.Validate(msg) if err != nil { return err diff --git a/x/model/types/messages_model_version_test.go b/x/model/types/messages_model_version_test.go index fdf310be1..39621cecf 100644 --- a/x/model/types/messages_model_version_test.go +++ b/x/model/types/messages_model_version_test.go @@ -208,25 +208,67 @@ func TestMsgCreateModelVersion_ValidateBasic(t *testing.T) { return msg }(validMsgCreateModelVersion()), - err: validator.ErrRequiredFieldMissing, + err: ErrOtaChecksumTypeInvalid, }, { - name: "OtaChecksumType < 0", + name: "OtaChecksumType < 0 when OtaUrl is set", msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" msg.OtaChecksumType = -1 return msg }(validMsgCreateModelVersion()), - err: validator.ErrFieldLowerBoundViolated, + err: ErrOtaChecksumTypeInvalid, }, { - name: "OtaChecksumType > 65535", + name: "OtaChecksumType > 65535 when OtaUrl is set", msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" msg.OtaChecksumType = 65536 return msg }(validMsgCreateModelVersion()), - err: validator.ErrFieldUpperBoundViolated, + err: ErrOtaChecksumTypeInvalid, + }, + { + name: "OtaChecksumType == 2 is not in allowed list when OtaUrl is set", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 2 + + return msg + }(validMsgCreateModelVersion()), + err: ErrOtaChecksumTypeInvalid, + }, + { + name: "OtaChecksumType == 3 is not in allowed list when OtaUrl is set", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 3 + + return msg + }(validMsgCreateModelVersion()), + err: ErrOtaChecksumTypeInvalid, + }, + { + name: "OtaChecksumType == 9 is not in allowed list when OtaUrl is set", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 9 + + return msg + }(validMsgCreateModelVersion()), + err: ErrOtaChecksumTypeInvalid, + }, + { + name: "OtaChecksumType == 100 is not in allowed list when OtaUrl is set", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 100 + + return msg + }(validMsgCreateModelVersion()), + err: ErrOtaChecksumTypeInvalid, }, { name: "MinApplicableSoftwareVersion > MaxApplicableSoftwareVersion " + @@ -488,17 +530,55 @@ func TestMsgCreateModelVersion_ValidateBasic(t *testing.T) { }(validMsgCreateModelVersion()), }, { - name: "OtaChecksumType == 1", + name: "OtaChecksumType == 1 (sha-256)", msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" msg.OtaChecksumType = 1 return msg }(validMsgCreateModelVersion()), }, { - name: "OtaChecksumType == 65535", + name: "OtaChecksumType == 7 (sha-384)", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 7 + + return msg + }(validMsgCreateModelVersion()), + }, + { + name: "OtaChecksumType == 8 (sha-512)", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 8 + + return msg + }(validMsgCreateModelVersion()), + }, + { + name: "OtaChecksumType == 10 (sha3-256)", msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { - msg.OtaChecksumType = 65535 + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 10 + + return msg + }(validMsgCreateModelVersion()), + }, + { + name: "OtaChecksumType == 11 (sha3-384)", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 11 + + return msg + }(validMsgCreateModelVersion()), + }, + { + name: "OtaChecksumType == 12 (sha3-512)", + msg: func(msg *MsgCreateModelVersion) *MsgCreateModelVersion { + msg.OtaUrl = "https://sampleflowurl.dclmodel" + msg.OtaChecksumType = 12 return msg }(validMsgCreateModelVersion()),