Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse additional features, basic support SecretProtect table, and small fixes #117

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/gosedctl/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func (r *revertNoeraseCmd) Run(ctx *context) error {
return fmt.Errorf("authenticating as Admin1 failed: %v", err)
}

if err := table.RevertLockingSP(lockingSession, true, pwhash); err != nil {
if err := table.RevertLockingSP(lockingSession, true); err != nil {
return fmt.Errorf("RevertLockingSP() failed: %v", err)
}
return nil
Expand Down
3 changes: 3 additions & 0 deletions cmd/tcgsdiag/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ func main() {
log.Printf("Locking SP LockingInfo:")
spew.Dump(table.LockingInfo(s))

log.Printf("Locking SP LockingSecretProtect:")
spew.Dump(table.LockingSecretProtect(s))

log.Printf("Locking SP MBRTableInfo:")
mbi, err := table.MBR_TableInfo(s)
if err != nil {
Expand Down
55 changes: 29 additions & 26 deletions pkg/core/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ type Core struct {
}

func NewCore(device string) (*Core, error) {
drive, err := drive.Open(device)
d, err := drive.Open(device)
if err != nil {
return nil, fmt.Errorf("open device %s failed: %v", device, err)
}
ident, err := drive.Identify()
ident, err := d.Identify()
if err != nil {
return nil, fmt.Errorf("identify device %s failed: %v", device, err)
}
c := &Core{
DriveIntf: drive,
DriveIntf: d,
DiskInfo: DiskInfo{
Identity: ident,
Level0Discovery: &Level0Discovery{},
Expand All @@ -49,29 +49,30 @@ type DiskInfo struct {
// Level0Discovery structure as described in TCG Storage Architecture Core Spec v2.01 rev 1.00
// (missing data length field, which is only required for parsing)
type Level0Discovery struct {
MajorVersion int
MinorVersion int
Vendor [32]byte
TPer *feature.TPer
Locking *feature.Locking
Geometry *feature.Geometry
SecureMsg *feature.SecureMsg
Enterprise *feature.Enterprise
OpalV1 *feature.OpalV1
SingleUser *feature.SingleUser
DataStore *feature.DataStore
OpalV2 *feature.OpalV2
Opalite *feature.Opalite
PyriteV1 *feature.PyriteV1
PyriteV2 *feature.PyriteV2
RubyV1 *feature.RubyV1
LockingLBA *feature.LockingLBA
BlockSID *feature.BlockSID
NamespaceLocking *feature.NamespaceLocking
DataRemoval *feature.DataRemoval
NamespaceGeometry *feature.NamespaceGeometry
SeagatePorts *feature.SeagatePorts
UnknownFeatures []uint16
MajorVersion int
MinorVersion int
Vendor [32]byte
TPer *feature.TPer
Locking *feature.Locking
Geometry *feature.Geometry
SecureMsg *feature.SecureMsg
Enterprise *feature.Enterprise
OpalV1 *feature.OpalV1
SingleUser *feature.SingleUser
DataStore *feature.DataStore
OpalV2 *feature.OpalV2
Opalite *feature.Opalite
PyriteV1 *feature.PyriteV1
PyriteV2 *feature.PyriteV2
RubyV1 *feature.RubyV1
LockingLBA *feature.LockingLBA
BlockSID *feature.BlockSID
NamespaceLocking *feature.NamespaceLocking
DataRemoval *feature.DataRemoval
NamespaceGeometry *feature.NamespaceGeometry
ShadowMBRForMultipleNamespaces *feature.ShadowMBRForMultipleNamespaces
SeagatePorts *feature.SeagatePorts
UnknownFeatures []uint16
}

// Perform a Level 0 SSC Discovery.
Expand Down Expand Up @@ -151,6 +152,8 @@ func (d *Core) Discovery0() error {
d0.DataRemoval, err = feature.ReadDataRemovalFeature(frdr)
case feature.CodeNamespaceGeometry:
d0.NamespaceGeometry, err = feature.ReadNamespaceGeometryFeature(frdr)
case feature.CodeShadowMBRForMultipleNamespaces:
d0.ShadowMBRForMultipleNamespaces, err = feature.ReadShadowMBRForMultipleNamespacesFeature(frdr)
case feature.CodeSeagatePorts:
d0.SeagatePorts, err = feature.ReadSeagatePorts(frdr)
default:
Expand Down
127 changes: 99 additions & 28 deletions pkg/core/feature/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,26 @@ import (
type FeatureCode uint16

const (
CodeTPer FeatureCode = 0x0001
CodeLocking FeatureCode = 0x0002
CodeGeometry FeatureCode = 0x0003
CodeSecureMsg FeatureCode = 0x0004
CodeEnterprise FeatureCode = 0x0100
CodeOpalV1 FeatureCode = 0x0200
CodeSingleUser FeatureCode = 0x0201
CodeDataStore FeatureCode = 0x0202
CodeOpalV2 FeatureCode = 0x0203
CodeOpalite FeatureCode = 0x0301
CodePyriteV1 FeatureCode = 0x0302
CodePyriteV2 FeatureCode = 0x0303
CodeRubyV1 FeatureCode = 0x0304
CodeLockingLBA FeatureCode = 0x0401
CodeBlockSID FeatureCode = 0x0402
CodeNamespaceLocking FeatureCode = 0x0403
CodeDataRemoval FeatureCode = 0x0404
CodeNamespaceGeometry FeatureCode = 0x0405
CodeSeagatePorts FeatureCode = 0xC001
CodeTPer FeatureCode = 0x0001
CodeLocking FeatureCode = 0x0002
CodeGeometry FeatureCode = 0x0003
CodeSecureMsg FeatureCode = 0x0004
CodeEnterprise FeatureCode = 0x0100
CodeOpalV1 FeatureCode = 0x0200
CodeSingleUser FeatureCode = 0x0201
CodeDataStore FeatureCode = 0x0202
CodeOpalV2 FeatureCode = 0x0203
CodeOpalite FeatureCode = 0x0301
CodePyriteV1 FeatureCode = 0x0302
CodePyriteV2 FeatureCode = 0x0303
CodeRubyV1 FeatureCode = 0x0304
CodeLockingLBA FeatureCode = 0x0401
CodeBlockSID FeatureCode = 0x0402
CodeNamespaceLocking FeatureCode = 0x0403
CodeDataRemoval FeatureCode = 0x0404
CodeNamespaceGeometry FeatureCode = 0x0405
CodeShadowMBRForMultipleNamespaces FeatureCode = 0x0407
CodeSeagatePorts FeatureCode = 0xC001
)

type TPer struct {
Expand Down Expand Up @@ -60,8 +61,12 @@ type CommonSSC struct {
}

type Geometry struct {
// TODO
Align bool
LogicalBlockSize uint32
AlignmentGranularity uint64
LowestAlignedLBA uint64
}

type SecureMsg struct {
// TODO
}
Expand All @@ -75,7 +80,10 @@ type OpalV1 struct {
// TODO
}
type SingleUser struct {
// TODO
NumberLockingObjectsSupported uint32
Policy bool
Any bool
All bool
}
type DataStore struct {
// TODO
Expand Down Expand Up @@ -130,7 +138,12 @@ type BlockSID struct {
}

type NamespaceLocking struct {
// TODO
Range_C bool
Range_P bool
SUM_C bool
MaximumKeyCount uint32
UnusedKeyCount uint32
MaximumRangesPerNamespace uint32
}
type DataRemoval struct {
// TODO
Expand All @@ -144,6 +157,10 @@ type SeagatePort struct {
PortLocked uint8
}

type ShadowMBRForMultipleNamespaces struct {
ANS_C bool
}

type SeagatePorts struct {
Ports []SeagatePort
}
Expand Down Expand Up @@ -181,8 +198,22 @@ func ReadLockingFeature(rdr io.Reader) (*Locking, error) {
}

func ReadGeometryFeature(rdr io.Reader) (*Geometry, error) {
f := &Geometry{}
return f, nil
d := struct {
Align uint8
_ [7]byte
LogicalBlockSize uint32
AlignmentGranularity uint64
LowestAlignedLBA uint64
}{}
if err := binary.Read(rdr, binary.BigEndian, &d); err != nil {
return nil, err
}
return &Geometry{
Align: d.Align&0x1 > 0,
LogicalBlockSize: d.LogicalBlockSize,
AlignmentGranularity: d.AlignmentGranularity,
LowestAlignedLBA: d.LowestAlignedLBA,
}, nil
}

func ReadSecureMsgFeature(rdr io.Reader) (*SecureMsg, error) {
Expand All @@ -204,8 +235,20 @@ func ReadOpalV1Feature(rdr io.Reader) (*OpalV1, error) {
}

func ReadSingleUserFeature(rdr io.Reader) (*SingleUser, error) {
f := &SingleUser{}
return f, nil
d := struct {
NumberOfLockingObjectsSupported uint32
Policy uint8
_ [7]byte
}{}
if err := binary.Read(rdr, binary.BigEndian, &d); err != nil {
return nil, err
}
return &SingleUser{
NumberLockingObjectsSupported: d.NumberOfLockingObjectsSupported,
Policy: d.Policy&0x4 > 0,
All: d.Policy&0x2 > 0,
Any: d.Policy&0x1 > 0,
}, nil
}

func ReadDataStoreFeature(rdr io.Reader) (*DataStore, error) {
Expand Down Expand Up @@ -273,8 +316,25 @@ func ReadBlockSIDFeature(rdr io.Reader) (*BlockSID, error) {
}

func ReadNamespaceLockingFeature(rdr io.Reader) (*NamespaceLocking, error) {
f := &NamespaceLocking{}
return f, nil
d := struct {
Range uint8
_ [3]byte
MaximumKeyCount uint32
UnusedKeyCount uint32
MaximumRangesPerNamespace uint32
}{}
if err := binary.Read(rdr, binary.BigEndian, &d); err != nil {
return nil, err
}

return &NamespaceLocking{
Range_C: d.Range&0x80 > 0,
Range_P: d.Range&0x40 > 0,
SUM_C: d.Range&0x20 > 0,
MaximumKeyCount: d.MaximumKeyCount,
UnusedKeyCount: d.UnusedKeyCount,
MaximumRangesPerNamespace: d.MaximumRangesPerNamespace,
}, nil
}

func ReadDataRemovalFeature(rdr io.Reader) (*DataRemoval, error) {
Expand All @@ -287,6 +347,17 @@ func ReadNamespaceGeometryFeature(rdr io.Reader) (*NamespaceGeometry, error) {
return f, nil
}

func ReadShadowMBRForMultipleNamespacesFeature(rdr io.Reader) (*ShadowMBRForMultipleNamespaces, error) {
var raw uint8
if err := binary.Read(rdr, binary.BigEndian, &raw); err != nil {
return nil, err
}

return &ShadowMBRForMultipleNamespaces{
ANS_C: raw&0x1 > 0,
}, nil
}

func ReadSeagatePorts(rdr io.Reader) (*SeagatePorts, error) {
f := &SeagatePorts{}
for {
Expand Down
77 changes: 73 additions & 4 deletions pkg/core/table/locking.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,27 @@ const (
ResetPowerOff ResetType = 0
ResetHardware ResetType = 1
ResetHotPlug ResetType = 2
// The parameter number for KeepGlobalRangeKey SHALL be 0x060000
// TCG Storage Security Subsystem Class: Opal | Version 2.02 | Revision 1.0 | Page 86
KeepGlobalRangeKey uint = 0x060000
)

type ProtectMechanism uint

const (
VendorUnique ProtectMechanism = 0
AuthenticationDataRequired ProtectMechanism = 1
)

type SecretProtect struct {
UID uid.UID
Table uid.RowUID
Column uint
ProtectMechanism []ProtectMechanism
}

const ProtectMechanismColumn uint = 3

type LockingInfoRow struct {
UID uid.RowUID
Name *string
Expand All @@ -59,6 +78,58 @@ func LockingSPActivate(s *core.Session) error {
return nil
}

func LockingSecretProtect(s *core.Session) ([]SecretProtect, error) {
if uids, err := Enumerate(s, uid.Locking_SecretProtect); err != nil {
return nil, err
} else {
result := make([]SecretProtect, len(uids))
for i, rowUid := range uids {
val, err := GetFullRow(s, rowUid)
if err != nil {
return nil, err
}

for col, val := range val {
switch col {
case "0", "UID":
v, ok := val.([]byte)
if !ok {
return nil, method.ErrMalformedMethodResponse
}
copy(result[i].UID[:], v[:8])
case "1", "Table":
v, ok := val.([]byte)
if !ok {
return nil, method.ErrMalformedMethodResponse
}
copy(result[i].Table[:], v[:8])
case "2", "Column":
v, ok := val.(uint)
if !ok {
return nil, method.ErrMalformedMethodResponse
}
result[i].Column = v
case "3", "ProtectMechanisms":
v, ok := val.(stream.List)
if !ok {
return nil, method.ErrMalformedMethodResponse
}
mechanisms := make([]ProtectMechanism, len(v))
for n, val := range v {
mechanism, ok := val.(uint)
if !ok {
return nil, method.ErrMalformedMethodResponse
}
mechanisms[n] = ProtectMechanism(mechanism)
}
result[i].ProtectMechanism = mechanisms
}
}
}
return result, nil
}
}

func LockingInfo(s *core.Session) (*LockingInfoRow, error) {
rowUID := uid.RowUID{}
if s.ProtocolLevel == core.ProtocolLevelEnterprise {
Expand Down Expand Up @@ -548,13 +619,11 @@ func LoadPBAImage(s *core.Session, image []byte) error {
return nil
}

func RevertLockingSP(s *core.Session, keep bool, pwhash []byte) error {
func RevertLockingSP(s *core.Session, keep bool) error {
mc := method.NewMethodCall(uid.InvokeIDThisSP, uid.OpalRevertSP, s.MethodFlags)
if keep {
mc.Token(stream.StartName)
// KeepGlobalRangeKey, TCG Storage Security Subsystem Class: Opal | Version 2.02 | Revision 1.0 | Page 85
// sedutil-cli looks like a Short-Atom without byte or integer indicator
mc.RawByte([]byte{0x83, 0x06, 0x00, 0x00})
mc.UInt(KeepGlobalRangeKey)
mc.Token(stream.OpalTrue)
mc.Token(stream.EndName)
}
Expand Down
Loading