mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
COCOS-407 - Add support for Linux IMA (#429)
* Added a feature which enables users to fetch IMA measurements and verify them * Added a feature which enables users to fetch IMA measurements and verify them * fixed lint error * fixed according to comments * fixed according to comments * fixed according to comments * fixed according to comments * final bug fix
This commit is contained in:
@@ -33,6 +33,7 @@ const (
|
||||
eventLog = "/sys/kernel/security/tpm0/binary_bios_measurements"
|
||||
Nonce = 32
|
||||
PCR15 = 15
|
||||
Hash1 = 20
|
||||
Hash256 = 32
|
||||
Hash384 = 48
|
||||
)
|
||||
@@ -315,3 +316,30 @@ func calculatePCRTLSKey(pubKey []byte) ([]byte, []byte) {
|
||||
|
||||
return newPcr256[:], newPcr384[:]
|
||||
}
|
||||
|
||||
func getPCRValue(index int, algorithm tpm2.Algorithm) ([]byte, error) {
|
||||
rwc, err := OpenTpm()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rwc.Close()
|
||||
|
||||
pcrValue, err := tpm2.ReadPCR(rwc, index, algorithm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pcrValue, nil
|
||||
}
|
||||
|
||||
func GetPCRSHA1Value(index int) ([]byte, error) {
|
||||
return getPCRValue(index, tpm2.AlgSHA1)
|
||||
}
|
||||
|
||||
func GetPCRSHA256Value(index int) ([]byte, error) {
|
||||
return getPCRValue(index, tpm2.AlgSHA256)
|
||||
}
|
||||
|
||||
func GetPCRSHA384Value(index int) ([]byte, error) {
|
||||
return getPCRValue(index, tpm2.AlgSHA384)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/ultravioletrs/cocos/agent"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/vtpm"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
@@ -338,6 +339,22 @@ func (p *ProgressBar) ReceiveResult(description string, totalSize int, stream ag
|
||||
}, resultFile)
|
||||
}
|
||||
|
||||
func (p *ProgressBar) ReceiveIMAMeasurements(description string, totalSize int, stream agent.AgentService_IMAMeasurementsClient, resultFile *os.File) ([]byte, error) {
|
||||
pcr10 := make([]byte, vtpm.Hash1)
|
||||
err := p.receiveStream(description, totalSize, func() ([]byte, error) {
|
||||
response, err := stream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
copy(pcr10, response.Pcr10[:20])
|
||||
|
||||
return response.File, nil
|
||||
}, resultFile)
|
||||
|
||||
return pcr10, err
|
||||
}
|
||||
|
||||
func (p *ProgressBar) ReceiveAttestation(description string, totalSize int, stream agent.AgentService_AttestationClient, attestationFile *os.File) error {
|
||||
return p.receiveStream(description, totalSize, func() ([]byte, error) {
|
||||
response, err := stream.Recv()
|
||||
|
||||
+37
-6
@@ -27,15 +27,17 @@ type SDK interface {
|
||||
Data(ctx context.Context, dataset *os.File, filename string, privKey any) error
|
||||
Result(ctx context.Context, privKey any, resultFile *os.File) error
|
||||
Attestation(ctx context.Context, reportData [size64]byte, nonce [size32]byte, attType int, attestationFile *os.File) error
|
||||
IMAMeasurements(ctx context.Context, resultFile *os.File) ([]byte, error)
|
||||
}
|
||||
|
||||
const (
|
||||
size64 = 64
|
||||
size32 = 32
|
||||
algoProgressBarDescription = "Uploading algorithm"
|
||||
dataProgressBarDescription = "Uploading data"
|
||||
resultProgressDescription = "Downloading result"
|
||||
attestationProgressDescription = "Downloading attestation"
|
||||
size64 = 64
|
||||
size32 = 32
|
||||
algoProgressBarDescription = "Uploading algorithm"
|
||||
dataProgressBarDescription = "Uploading data"
|
||||
resultProgressDescription = "Downloading result"
|
||||
attestationProgressDescription = "Downloading attestation"
|
||||
imaMeasurementsProgressDescription = "Downloading Linux IMA measurements"
|
||||
)
|
||||
|
||||
type agentSDK struct {
|
||||
@@ -186,3 +188,32 @@ func generateMetadata(userID string, privateKey crypto.PrivateKey) (metadata.MD,
|
||||
kv[auth.SignatureMetadataKey] = base64.StdEncoding.EncodeToString(signature)
|
||||
return metadata.New(kv), nil
|
||||
}
|
||||
|
||||
func (sdk *agentSDK) IMAMeasurements(ctx context.Context, resultFile *os.File) ([]byte, error) {
|
||||
request := &agent.IMAMeasurementsRequest{}
|
||||
|
||||
stream, err := sdk.client.IMAMeasurements(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
incomingmd, err := stream.Header()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileSizeStr := incomingmd.Get(grpc.FileSizeKey)
|
||||
|
||||
if len(fileSizeStr) == 0 {
|
||||
fileSizeStr = append(fileSizeStr, "0")
|
||||
}
|
||||
|
||||
fileSize, err := strconv.Atoi(fileSizeStr[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pb := progressbar.New(true)
|
||||
|
||||
return pb.ReceiveIMAMeasurements(imaMeasurementsProgressDescription, fileSize, stream, resultFile)
|
||||
}
|
||||
|
||||
@@ -173,6 +173,65 @@ func (_c *SDK_Data_Call) RunAndReturn(run func(context.Context, *os.File, string
|
||||
return _c
|
||||
}
|
||||
|
||||
// IMAMeasurements provides a mock function with given fields: ctx, resultFile
|
||||
func (_m *SDK) IMAMeasurements(ctx context.Context, resultFile *os.File) ([]byte, error) {
|
||||
ret := _m.Called(ctx, resultFile)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for IMAMeasurements")
|
||||
}
|
||||
|
||||
var r0 []byte
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *os.File) ([]byte, error)); ok {
|
||||
return rf(ctx, resultFile)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *os.File) []byte); ok {
|
||||
r0 = rf(ctx, resultFile)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *os.File) error); ok {
|
||||
r1 = rf(ctx, resultFile)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SDK_IMAMeasurements_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IMAMeasurements'
|
||||
type SDK_IMAMeasurements_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// IMAMeasurements is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - resultFile *os.File
|
||||
func (_e *SDK_Expecter) IMAMeasurements(ctx interface{}, resultFile interface{}) *SDK_IMAMeasurements_Call {
|
||||
return &SDK_IMAMeasurements_Call{Call: _e.mock.On("IMAMeasurements", ctx, resultFile)}
|
||||
}
|
||||
|
||||
func (_c *SDK_IMAMeasurements_Call) Run(run func(ctx context.Context, resultFile *os.File)) *SDK_IMAMeasurements_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*os.File))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_IMAMeasurements_Call) Return(_a0 []byte, _a1 error) *SDK_IMAMeasurements_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_IMAMeasurements_Call) RunAndReturn(run func(context.Context, *os.File) ([]byte, error)) *SDK_IMAMeasurements_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Result provides a mock function with given fields: ctx, privKey, resultFile
|
||||
func (_m *SDK) Result(ctx context.Context, privKey interface{}, resultFile *os.File) error {
|
||||
ret := _m.Called(ctx, privKey, resultFile)
|
||||
|
||||
Reference in New Issue
Block a user