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:
+137
-34
@@ -384,6 +384,94 @@ func (x *AttestationResponse) GetFile() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type IMAMeasurementsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsRequest) Reset() {
|
||||
*x = IMAMeasurementsRequest{}
|
||||
mi := &file_agent_agent_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*IMAMeasurementsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *IMAMeasurementsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_agent_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use IMAMeasurementsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*IMAMeasurementsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_agent_agent_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
type IMAMeasurementsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
File []byte `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"`
|
||||
Pcr10 []byte `protobuf:"bytes,2,opt,name=pcr10,proto3" json:"pcr10,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsResponse) Reset() {
|
||||
*x = IMAMeasurementsResponse{}
|
||||
mi := &file_agent_agent_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*IMAMeasurementsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *IMAMeasurementsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_agent_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use IMAMeasurementsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*IMAMeasurementsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_agent_agent_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsResponse) GetFile() []byte {
|
||||
if x != nil {
|
||||
return x.File
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *IMAMeasurementsResponse) GetPcr10() []byte {
|
||||
if x != nil {
|
||||
return x.Pcr10
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_agent_agent_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_agent_agent_proto_rawDesc = string([]byte{
|
||||
@@ -412,24 +500,35 @@ var file_agent_agent_proto_rawDesc = string([]byte{
|
||||
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x29, 0x0a, 0x13, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x32, 0xfd, 0x01, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x41, 0x6c, 0x67, 0x6f, 0x12,
|
||||
0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x33, 0x0a, 0x04,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x61, 0x74,
|
||||
0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28,
|
||||
0x01, 0x12, 0x39, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0b,
|
||||
0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x18, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61,
|
||||
0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x22, 0x43, 0x0a, 0x17, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
|
||||
0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x70, 0x63, 0x72, 0x31, 0x30, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
|
||||
0x70, 0x63, 0x72, 0x31, 0x30, 0x32, 0xd3, 0x02, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x41, 0x6c, 0x67, 0x6f, 0x12, 0x12,
|
||||
0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x33, 0x0a, 0x04, 0x44,
|
||||
0x61, 0x74, 0x61, 0x12, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01,
|
||||
0x12, 0x39, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0b, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74,
|
||||
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0f, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73,
|
||||
0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e,
|
||||
0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
|
||||
var (
|
||||
@@ -444,28 +543,32 @@ func file_agent_agent_proto_rawDescGZIP() []byte {
|
||||
return file_agent_agent_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_agent_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||
var file_agent_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||
var file_agent_agent_proto_goTypes = []any{
|
||||
(*AlgoRequest)(nil), // 0: agent.AlgoRequest
|
||||
(*AlgoResponse)(nil), // 1: agent.AlgoResponse
|
||||
(*DataRequest)(nil), // 2: agent.DataRequest
|
||||
(*DataResponse)(nil), // 3: agent.DataResponse
|
||||
(*ResultRequest)(nil), // 4: agent.ResultRequest
|
||||
(*ResultResponse)(nil), // 5: agent.ResultResponse
|
||||
(*AttestationRequest)(nil), // 6: agent.AttestationRequest
|
||||
(*AttestationResponse)(nil), // 7: agent.AttestationResponse
|
||||
(*AlgoRequest)(nil), // 0: agent.AlgoRequest
|
||||
(*AlgoResponse)(nil), // 1: agent.AlgoResponse
|
||||
(*DataRequest)(nil), // 2: agent.DataRequest
|
||||
(*DataResponse)(nil), // 3: agent.DataResponse
|
||||
(*ResultRequest)(nil), // 4: agent.ResultRequest
|
||||
(*ResultResponse)(nil), // 5: agent.ResultResponse
|
||||
(*AttestationRequest)(nil), // 6: agent.AttestationRequest
|
||||
(*AttestationResponse)(nil), // 7: agent.AttestationResponse
|
||||
(*IMAMeasurementsRequest)(nil), // 8: agent.IMAMeasurementsRequest
|
||||
(*IMAMeasurementsResponse)(nil), // 9: agent.IMAMeasurementsResponse
|
||||
}
|
||||
var file_agent_agent_proto_depIdxs = []int32{
|
||||
0, // 0: agent.AgentService.Algo:input_type -> agent.AlgoRequest
|
||||
2, // 1: agent.AgentService.Data:input_type -> agent.DataRequest
|
||||
4, // 2: agent.AgentService.Result:input_type -> agent.ResultRequest
|
||||
6, // 3: agent.AgentService.Attestation:input_type -> agent.AttestationRequest
|
||||
1, // 4: agent.AgentService.Algo:output_type -> agent.AlgoResponse
|
||||
3, // 5: agent.AgentService.Data:output_type -> agent.DataResponse
|
||||
5, // 6: agent.AgentService.Result:output_type -> agent.ResultResponse
|
||||
7, // 7: agent.AgentService.Attestation:output_type -> agent.AttestationResponse
|
||||
4, // [4:8] is the sub-list for method output_type
|
||||
0, // [0:4] is the sub-list for method input_type
|
||||
8, // 4: agent.AgentService.IMAMeasurements:input_type -> agent.IMAMeasurementsRequest
|
||||
1, // 5: agent.AgentService.Algo:output_type -> agent.AlgoResponse
|
||||
3, // 6: agent.AgentService.Data:output_type -> agent.DataResponse
|
||||
5, // 7: agent.AgentService.Result:output_type -> agent.ResultResponse
|
||||
7, // 8: agent.AgentService.Attestation:output_type -> agent.AttestationResponse
|
||||
9, // 9: agent.AgentService.IMAMeasurements:output_type -> agent.IMAMeasurementsResponse
|
||||
5, // [5:10] is the sub-list for method output_type
|
||||
0, // [0:5] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
@@ -482,7 +585,7 @@ func file_agent_agent_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_agent_proto_rawDesc), len(file_agent_agent_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 8,
|
||||
NumMessages: 10,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ service AgentService {
|
||||
rpc Data(stream DataRequest) returns (DataResponse) {}
|
||||
rpc Result(ResultRequest) returns (stream ResultResponse) {}
|
||||
rpc Attestation(AttestationRequest) returns (stream AttestationResponse) {}
|
||||
rpc IMAMeasurements(IMAMeasurementsRequest) returns (stream IMAMeasurementsResponse) {}
|
||||
}
|
||||
|
||||
message AlgoRequest {
|
||||
@@ -44,3 +45,11 @@ message AttestationRequest {
|
||||
message AttestationResponse {
|
||||
bytes file = 1;
|
||||
}
|
||||
|
||||
message IMAMeasurementsRequest {
|
||||
}
|
||||
|
||||
message IMAMeasurementsResponse {
|
||||
bytes file = 1;
|
||||
bytes pcr10 = 2;
|
||||
}
|
||||
|
||||
+45
-4
@@ -22,10 +22,11 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
AgentService_Algo_FullMethodName = "/agent.AgentService/Algo"
|
||||
AgentService_Data_FullMethodName = "/agent.AgentService/Data"
|
||||
AgentService_Result_FullMethodName = "/agent.AgentService/Result"
|
||||
AgentService_Attestation_FullMethodName = "/agent.AgentService/Attestation"
|
||||
AgentService_Algo_FullMethodName = "/agent.AgentService/Algo"
|
||||
AgentService_Data_FullMethodName = "/agent.AgentService/Data"
|
||||
AgentService_Result_FullMethodName = "/agent.AgentService/Result"
|
||||
AgentService_Attestation_FullMethodName = "/agent.AgentService/Attestation"
|
||||
AgentService_IMAMeasurements_FullMethodName = "/agent.AgentService/IMAMeasurements"
|
||||
)
|
||||
|
||||
// AgentServiceClient is the client API for AgentService service.
|
||||
@@ -36,6 +37,7 @@ type AgentServiceClient interface {
|
||||
Data(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[DataRequest, DataResponse], error)
|
||||
Result(ctx context.Context, in *ResultRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ResultResponse], error)
|
||||
Attestation(ctx context.Context, in *AttestationRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AttestationResponse], error)
|
||||
IMAMeasurements(ctx context.Context, in *IMAMeasurementsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[IMAMeasurementsResponse], error)
|
||||
}
|
||||
|
||||
type agentServiceClient struct {
|
||||
@@ -110,6 +112,25 @@ func (c *agentServiceClient) Attestation(ctx context.Context, in *AttestationReq
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_AttestationClient = grpc.ServerStreamingClient[AttestationResponse]
|
||||
|
||||
func (c *agentServiceClient) IMAMeasurements(ctx context.Context, in *IMAMeasurementsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[IMAMeasurementsResponse], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &AgentService_ServiceDesc.Streams[4], AgentService_IMAMeasurements_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[IMAMeasurementsRequest, IMAMeasurementsResponse]{ClientStream: stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_IMAMeasurementsClient = grpc.ServerStreamingClient[IMAMeasurementsResponse]
|
||||
|
||||
// AgentServiceServer is the server API for AgentService service.
|
||||
// All implementations must embed UnimplementedAgentServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -118,6 +139,7 @@ type AgentServiceServer interface {
|
||||
Data(grpc.ClientStreamingServer[DataRequest, DataResponse]) error
|
||||
Result(*ResultRequest, grpc.ServerStreamingServer[ResultResponse]) error
|
||||
Attestation(*AttestationRequest, grpc.ServerStreamingServer[AttestationResponse]) error
|
||||
IMAMeasurements(*IMAMeasurementsRequest, grpc.ServerStreamingServer[IMAMeasurementsResponse]) error
|
||||
mustEmbedUnimplementedAgentServiceServer()
|
||||
}
|
||||
|
||||
@@ -140,6 +162,9 @@ func (UnimplementedAgentServiceServer) Result(*ResultRequest, grpc.ServerStreami
|
||||
func (UnimplementedAgentServiceServer) Attestation(*AttestationRequest, grpc.ServerStreamingServer[AttestationResponse]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Attestation not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServiceServer) IMAMeasurements(*IMAMeasurementsRequest, grpc.ServerStreamingServer[IMAMeasurementsResponse]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method IMAMeasurements not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServiceServer) mustEmbedUnimplementedAgentServiceServer() {}
|
||||
func (UnimplementedAgentServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -197,6 +222,17 @@ func _AgentService_Attestation_Handler(srv interface{}, stream grpc.ServerStream
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_AttestationServer = grpc.ServerStreamingServer[AttestationResponse]
|
||||
|
||||
func _AgentService_IMAMeasurements_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(IMAMeasurementsRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(AgentServiceServer).IMAMeasurements(m, &grpc.GenericServerStream[IMAMeasurementsRequest, IMAMeasurementsResponse]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_IMAMeasurementsServer = grpc.ServerStreamingServer[IMAMeasurementsResponse]
|
||||
|
||||
// AgentService_ServiceDesc is the grpc.ServiceDesc for AgentService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -225,6 +261,11 @@ var AgentService_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _AgentService_Attestation_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "IMAMeasurements",
|
||||
Handler: _AgentService_IMAMeasurements_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "agent/agent.proto",
|
||||
}
|
||||
|
||||
@@ -79,3 +79,19 @@ func attestationEndpoint(svc agent.Service) endpoint.Endpoint {
|
||||
return attestationRes{File: file}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func imaMeasurementsEndpoint(svc agent.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(imaMeasurementsReq)
|
||||
|
||||
if err := req.validate(); err != nil {
|
||||
return imaMeasurementsRes{}, err
|
||||
}
|
||||
file, pcr10, err := svc.IMAMeasurements(ctx)
|
||||
if err != nil {
|
||||
return imaMeasurementsRes{}, err
|
||||
}
|
||||
|
||||
return imaMeasurementsRes{File: file, PCR10: pcr10}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,3 +55,10 @@ func (req attestationReq) validate() error {
|
||||
return errors.New("invalid attestation type in attestation request")
|
||||
}
|
||||
}
|
||||
|
||||
type imaMeasurementsReq struct{}
|
||||
|
||||
func (req imaMeasurementsReq) validate() error {
|
||||
// No request parameters to validate, so no validation logic needed
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,3 +13,8 @@ type resultRes struct {
|
||||
type attestationRes struct {
|
||||
File []byte
|
||||
}
|
||||
|
||||
type imaMeasurementsRes struct {
|
||||
File []byte
|
||||
PCR10 []byte
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-kit/kit/transport/grpc"
|
||||
"github.com/ultravioletrs/cocos/agent"
|
||||
@@ -32,10 +33,11 @@ var (
|
||||
var _ agent.AgentServiceServer = (*grpcServer)(nil)
|
||||
|
||||
type grpcServer struct {
|
||||
algo grpc.Handler
|
||||
data grpc.Handler
|
||||
result grpc.Handler
|
||||
attestation grpc.Handler
|
||||
algo grpc.Handler
|
||||
data grpc.Handler
|
||||
result grpc.Handler
|
||||
attestation grpc.Handler
|
||||
imaMeasurements grpc.Handler
|
||||
agent.UnimplementedAgentServiceServer
|
||||
}
|
||||
|
||||
@@ -62,6 +64,11 @@ func NewServer(svc agent.Service) agent.AgentServiceServer {
|
||||
decodeAttestationRequest,
|
||||
encodeAttestationResponse,
|
||||
),
|
||||
imaMeasurements: grpc.NewServer(
|
||||
imaMeasurementsEndpoint(svc),
|
||||
decodeIMAMeasurementsRequest,
|
||||
encodeIMAMeasurementsResponse,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,3 +242,56 @@ func (s *grpcServer) Attestation(req *agent.AttestationRequest, stream agent.Age
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeIMAMeasurementsRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
return imaMeasurementsReq{}, nil
|
||||
}
|
||||
|
||||
func encodeIMAMeasurementsResponse(_ context.Context, response interface{}) (interface{}, error) {
|
||||
res := response.(imaMeasurementsRes)
|
||||
return &agent.IMAMeasurementsResponse{
|
||||
File: res.File,
|
||||
Pcr10: res.PCR10,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *grpcServer) IMAMeasurements(req *agent.IMAMeasurementsRequest, stream agent.AgentService_IMAMeasurementsServer) error {
|
||||
_, res, err := s.imaMeasurements.ServeGRPC(stream.Context(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rr := res.(*agent.IMAMeasurementsResponse)
|
||||
|
||||
if err := stream.SetHeader(metadata.New(map[string]string{FileSizeKey: strconv.Itoa(len(rr.File))})); err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
imaBuff := bytes.NewBuffer(rr.File)
|
||||
pcr10Buff := bytes.NewBuffer(rr.Pcr10)
|
||||
|
||||
imaResBuff := make([]byte, bufferSize)
|
||||
pcr10ResBuff := make([]byte, bufferSize)
|
||||
|
||||
for {
|
||||
nIma, errIma := imaBuff.Read(imaResBuff)
|
||||
if errIma != nil && errIma != io.EOF {
|
||||
return status.Error(codes.Internal, errIma.Error())
|
||||
}
|
||||
|
||||
nPcr, errPcr := pcr10Buff.Read(pcr10ResBuff)
|
||||
if errPcr != nil && errPcr != io.EOF {
|
||||
return status.Error(codes.Internal, errPcr.Error())
|
||||
}
|
||||
|
||||
if nIma == 0 && errIma == io.EOF &&
|
||||
nPcr == 0 && errPcr == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if err := stream.Send(&agent.IMAMeasurementsResponse{File: imaResBuff[:nIma], Pcr10: pcr10ResBuff[:nPcr]}); err != nil {
|
||||
return status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -118,3 +118,16 @@ func (lm *loggingMiddleware) Attestation(ctx context.Context, reportData [quotep
|
||||
|
||||
return lm.svc.Attestation(ctx, reportData, nonce, attType)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) IMAMeasurements(ctx context.Context) (file []byte, pcr10 []byte, err error) {
|
||||
defer func(begin time.Time) {
|
||||
message := fmt.Sprintf("Method IMAMeasurements took %s to complete", time.Since(begin))
|
||||
if err != nil {
|
||||
lm.logger.Warn(fmt.Sprintf("%s with error: %s", message, err))
|
||||
return
|
||||
}
|
||||
lm.logger.Info(fmt.Sprintf("%s without errors", message))
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.IMAMeasurements(ctx)
|
||||
}
|
||||
|
||||
@@ -100,3 +100,12 @@ func (ms *metricsMiddleware) Attestation(ctx context.Context, reportData [quotep
|
||||
|
||||
return ms.svc.Attestation(ctx, reportData, nonce, attType)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) IMAMeasurements(ctx context.Context) ([]byte, []byte, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "imameasurements").Add(1)
|
||||
ms.latency.With("method", "imameasurements").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return ms.svc.IMAMeasurements(ctx)
|
||||
}
|
||||
|
||||
@@ -182,6 +182,73 @@ func (_c *Service_Data_Call) RunAndReturn(run func(context.Context, agent.Datase
|
||||
return _c
|
||||
}
|
||||
|
||||
// IMAMeasurements provides a mock function with given fields: ctx
|
||||
func (_m *Service) IMAMeasurements(ctx context.Context) ([]byte, []byte, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for IMAMeasurements")
|
||||
}
|
||||
|
||||
var r0 []byte
|
||||
var r1 []byte
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) ([]byte, []byte, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) []byte); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) []byte); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(2).(func(context.Context) error); ok {
|
||||
r2 = rf(ctx)
|
||||
} else {
|
||||
r2 = ret.Error(2)
|
||||
}
|
||||
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// Service_IMAMeasurements_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IMAMeasurements'
|
||||
type Service_IMAMeasurements_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// IMAMeasurements is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
func (_e *Service_Expecter) IMAMeasurements(ctx interface{}) *Service_IMAMeasurements_Call {
|
||||
return &Service_IMAMeasurements_Call{Call: _e.mock.On("IMAMeasurements", ctx)}
|
||||
}
|
||||
|
||||
func (_c *Service_IMAMeasurements_Call) Run(run func(ctx context.Context)) *Service_IMAMeasurements_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_IMAMeasurements_Call) Return(_a0 []byte, _a1 []byte, _a2 error) *Service_IMAMeasurements_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_IMAMeasurements_Call) RunAndReturn(run func(context.Context) ([]byte, []byte, error)) *Service_IMAMeasurements_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// InitComputation provides a mock function with given fields: ctx, cmp
|
||||
func (_m *Service) InitComputation(ctx context.Context, cmp agent.Computation) error {
|
||||
ret := _m.Called(ctx, cmp)
|
||||
|
||||
@@ -75,6 +75,11 @@ const (
|
||||
algoFilePermission = 0o700
|
||||
)
|
||||
|
||||
const (
|
||||
ImaMeasurementsFilePath = "/sys/kernel/security/integrity/ima/ascii_runtime_measurements"
|
||||
ImaPcrIndex = 10
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrMalformedEntity indicates malformed entity specification (e.g.
|
||||
// invalid username or password).
|
||||
@@ -113,6 +118,7 @@ type Service interface {
|
||||
Data(ctx context.Context, dataset Dataset) error
|
||||
Result(ctx context.Context) ([]byte, error)
|
||||
Attestation(ctx context.Context, reportData [quoteprovider.Nonce]byte, nonce [vtpm.Nonce]byte, attType config.AttestationType) ([]byte, error)
|
||||
IMAMeasurements(ctx context.Context) ([]byte, []byte, error)
|
||||
State() string
|
||||
}
|
||||
|
||||
@@ -495,3 +501,17 @@ func (as *agentService) publishEvent(status string) statemachine.Action {
|
||||
as.eventSvc.SendEvent(as.computation.ID, state.String(), status, json.RawMessage{})
|
||||
}
|
||||
}
|
||||
|
||||
func (as *agentService) IMAMeasurements(ctx context.Context) ([]byte, []byte, error) {
|
||||
data, err := os.ReadFile(ImaMeasurementsFilePath)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error reading Linux IMA measurements file: %s", err.Error())
|
||||
}
|
||||
|
||||
pcr10, err := vtpm.GetPCRSHA1Value(ImaPcrIndex)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Error reading TPM PCR #10: %s", err.Error())
|
||||
}
|
||||
|
||||
return data, pcr10, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/vtpm"
|
||||
)
|
||||
|
||||
const (
|
||||
imaMeasurementsFilename = "ima_measurements"
|
||||
)
|
||||
|
||||
func (cli *CLI) NewIMAMeasurementsCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "ima-measurements",
|
||||
Short: "Retrieve Linux IMA measurements file",
|
||||
Example: "ima-measurements <optional_file_name>",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if cli.connectErr != nil {
|
||||
printError(cmd, "Failed to connect to agent: %v ❌ ", cli.connectErr)
|
||||
return
|
||||
}
|
||||
|
||||
cmd.Println("⏳ Retrieving computation Linux IMA measurements file")
|
||||
|
||||
filename := imaMeasurementsFilename
|
||||
if len(args) >= 1 {
|
||||
filename = args[0]
|
||||
}
|
||||
|
||||
imaMeasurementsFile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
printError(cmd, "Error creating imaMeasurements file: %v ❌ ", err)
|
||||
return
|
||||
}
|
||||
defer imaMeasurementsFile.Close()
|
||||
|
||||
pcr10, err := cli.agentSDK.IMAMeasurements(cmd.Context(), imaMeasurementsFile)
|
||||
if err != nil {
|
||||
printError(cmd, "Error retrieving Linux IMA measurements file: %v ❌ ", err)
|
||||
return
|
||||
}
|
||||
|
||||
cmd.Println(color.New(color.FgGreen).Sprintf("Linux IMA measurements file retrieved and saved successfully as %s! PCR10 = %s ✔ ", filename, hex.EncodeToString(pcr10)))
|
||||
|
||||
calculatedPCR10 := make([]byte, vtpm.Hash1)
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
printError(cmd, "Failed to open file: %v ❌ ", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.Fields(line)
|
||||
|
||||
if parts[0] != "10" {
|
||||
continue
|
||||
}
|
||||
|
||||
digestHex := parts[1]
|
||||
if digestHex == strings.Repeat("0", 40) {
|
||||
digestHex = strings.Repeat("f", 40)
|
||||
}
|
||||
|
||||
digest, err := hex.DecodeString(digestHex)
|
||||
if err != nil {
|
||||
printError(cmd, "Failed to decode digest: %v ❌ ", err)
|
||||
continue
|
||||
}
|
||||
|
||||
hasher := sha1.New()
|
||||
hasher.Write(calculatedPCR10)
|
||||
hasher.Write(digest)
|
||||
calculatedPCR10 = hasher.Sum(nil)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(pcr10) != hex.EncodeToString(calculatedPCR10) {
|
||||
printError(cmd, "Measurements file not verified ❌ ", err)
|
||||
} else {
|
||||
cmd.Println(color.New(color.FgGreen).Sprintf("Measurements file verified!"))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,7 @@ func main() {
|
||||
rootCmd.AddCommand(cliSVC.NewCABundleCmd(directoryCachePath))
|
||||
rootCmd.AddCommand(cliSVC.NewCreateVMCmd())
|
||||
rootCmd.AddCommand(cliSVC.NewRemoveVMCmd())
|
||||
rootCmd.AddCommand(cliSVC.NewIMAMeasurementsCmd())
|
||||
|
||||
// Attestation commands
|
||||
attestationCmd.AddCommand(cliSVC.NewGetAttestationCmd())
|
||||
|
||||
@@ -233,8 +233,39 @@ write_files:
|
||||
|
||||
echo "algo_user setup completed successfully"
|
||||
permissions: "0755"
|
||||
|
||||
# IMA setup for first boot
|
||||
- path: /cocos_init/linux_ima_init.sh
|
||||
content: |
|
||||
#!/bin/bash
|
||||
|
||||
GRUB_FILE="/etc/default/grub"
|
||||
|
||||
if ! grep -q '^GRUB_CMDLINE_LINUX=.*ima_policy' "$GRUB_FILE"; then
|
||||
echo "First boot, rebooting with fix IMA appraise policy"
|
||||
|
||||
NEW_PARAMS='ima_policy=tcb'
|
||||
|
||||
# Modify the GRUB_CMDLINE_LINUX line
|
||||
sed -i -E \
|
||||
"s#^(GRUB_CMDLINE_LINUX=\")(.*)(\")#\1\2 $NEW_PARAMS\3#" \
|
||||
"$GRUB_FILE"
|
||||
|
||||
echo "Updated GRUB_CMDLINE_LINUX:"
|
||||
grep "^GRUB_CMDLINE_LINUX=" "$GRUB_FILE"
|
||||
|
||||
sudo update-grub
|
||||
sudo reboot
|
||||
else
|
||||
sudo find / -fstype ext4 -type f -uid 0 -exec dd if='{}' of=/dev/null count=0 status=none \;
|
||||
fi
|
||||
permissions: "0755"
|
||||
|
||||
runcmd:
|
||||
# Enable Linux IMA with fix policy
|
||||
- echo "Enable Linux IMA with fix policy and rebooting if necessary"
|
||||
- sh /cocos_init/linux_ima_init.sh
|
||||
|
||||
# Create necessary directories
|
||||
- mkdir -p /cocos
|
||||
- mkdir -p /cocos_init
|
||||
|
||||
@@ -111,7 +111,6 @@ construct_qemu_args() {
|
||||
fi
|
||||
|
||||
args+=("-monitor" "$MONITOR")
|
||||
args+=("-no-reboot")
|
||||
args+=("-vnc" ":9")
|
||||
|
||||
echo "${args[@]}"
|
||||
|
||||
@@ -76,3 +76,17 @@ CONFIG_9P_FS_SECURITY=y
|
||||
CONFIG_TCG_TPM=y
|
||||
CONFIG_TCG_TPM2_HMAC=y
|
||||
CONFIG_TCG_PLATFORM=y
|
||||
|
||||
# Linux IMA
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_INTEGRITY=y
|
||||
CONFIG_INTEGRITY_SIGNATURE=y
|
||||
CONFIG_IMA=y
|
||||
CONFIG_IMA_MEASURE_PCR_IDX=10 # optional but good
|
||||
CONFIG_IMA_LSM_RULES=y
|
||||
CONFIG_IMA_APPRAISE=y # if you want appraisal (signature checking)
|
||||
CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_ENCRYPTED_KEYS=y # if you plan to use encrypted keys
|
||||
CONFIG_IMA_DEFAULT_HASH="sha256" # or sha1 if you prefer
|
||||
|
||||
@@ -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