NOISSUE - Extend the PCR16 with computation manifest JSON hash (#457)
CI / ci (push) Has been cancelled

* extend PCR16 with manifest

* fix ci

* fix PCR16 extension

* move pcr extension to executeRun

* put extension in a defer block
This commit is contained in:
Danko Miladinovic
2025-06-12 18:49:14 +02:00
committed by GitHub
parent 5960b06126
commit 3e474338c5
7 changed files with 59 additions and 26 deletions
+19
View File
@@ -4,6 +4,7 @@ package grpc
import (
"context"
"encoding/json"
"log/slog"
"sync"
"time"
@@ -13,6 +14,8 @@ import (
"github.com/ultravioletrs/cocos/agent/cvms"
"github.com/ultravioletrs/cocos/agent/cvms/api/grpc/storage"
"github.com/ultravioletrs/cocos/agent/cvms/server"
"github.com/ultravioletrs/cocos/pkg/attestation"
"github.com/ultravioletrs/cocos/pkg/attestation/vtpm"
pkggrpc "github.com/ultravioletrs/cocos/pkg/clients/grpc"
"golang.org/x/sync/errgroup"
"google.golang.org/protobuf/proto"
@@ -249,6 +252,8 @@ func (client *CVMSClient) executeRun(ctx context.Context, runReq *cvms.Computati
return
}
ccPlatform := attestation.CCPlatform()
client.mu.Lock()
defer client.mu.Unlock()
@@ -274,6 +279,20 @@ func (client *CVMSClient) executeRun(ctx context.Context, runReq *cvms.Computati
runRes.RunRes.Error = err.Error()
}
defer func() {
if ccPlatform == attestation.Azure || ccPlatform == attestation.SNPvTPM {
cmpJson, err := json.Marshal(ac)
if err != nil {
client.logger.Error(err.Error())
return
}
if err = vtpm.ExtendPCR(vtpm.PCR16, cmpJson); err != nil {
client.logger.Error(err.Error())
return
}
}
}()
client.sendMessage(&cvms.ClientStreamMessage{Message: runRes})
}
+2 -2
View File
@@ -520,12 +520,12 @@ func (as *agentService) publishEvent(status string) statemachine.Action {
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())
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 nil, nil, fmt.Errorf("error reading TPM PCR #10: %s", err.Error())
}
return data, pcr10, nil
+2
View File
@@ -41,6 +41,7 @@ func TestAlgo(t *testing.T) {
require.NoError(t, err)
algoHash := sha3.Sum256(algo)
vtpm.ExternalTPM = &vtpm.DummyRWC{}
reqFile, err := os.ReadFile(reqPath)
require.NoError(t, err)
@@ -142,6 +143,7 @@ func TestData(t *testing.T) {
require.NoError(t, err)
algoHash := sha3.Sum256(algo)
vtpm.ExternalTPM = &vtpm.DummyRWC{}
alg := Algorithm{
Hash: algoHash,
+1 -23
View File
@@ -30,28 +30,6 @@ const bufSize = 1024 * 1024
var lis *bufconn.Listener
type DummyRWC struct{}
// Read fills p with byte(len(p)) and returns len(p).
func (l *DummyRWC) Read(p []byte) (int, error) {
n := len(p)
// Fill each byte in p with the value of n as a byte.
for i := range p {
p[i] = byte(n)
}
return n, nil
}
// Write simply returns len(p) indicating that all bytes were written.
func (l *DummyRWC) Write(p []byte) (int, error) {
// In this simple implementation, we ignore the data.
return len(p), nil
}
func (l *DummyRWC) Close() error {
return nil
}
func init() {
lis = bufconn.Listen(bufSize)
}
@@ -277,7 +255,7 @@ func (b *ThreadSafeBuffer) String() string {
}
func TestServerInitializationAndStartup(t *testing.T) {
vtpm.ExternalTPM = &DummyRWC{}
vtpm.ExternalTPM = &vtpm.DummyRWC{}
testCases := []struct {
name string
+9 -1
View File
@@ -125,16 +125,24 @@ func SevGuesDeviceExists() bool {
}
func SevGuestvTPMExists() bool {
return vTPMExists() && SevGuesDeviceExists()
}
func vTPMExists() bool {
d, err := tpm2.OpenTPM()
if err != nil {
return false
}
d.Close()
return SevGuesDeviceExists()
return true
}
func isAzureVM() bool {
if !vTPMExists() {
return false
}
client := &http.Client{}
url := fmt.Sprintf("%s?api-version=%s", azureMetadataUrl, azureApiVersion)
+25
View File
@@ -0,0 +1,25 @@
// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package vtpm
type DummyRWC struct{}
// Read fills p with byte(len(p)) and returns len(p).
func (l *DummyRWC) Read(p []byte) (int, error) {
n := len(p)
// Fill each byte in p with the value of n as a byte.
for i := range p {
p[i] = byte(n)
}
return n, nil
}
// Write simply returns len(p) indicating that all bytes were written.
func (l *DummyRWC) Write(p []byte) (int, error) {
// In this simple implementation, we ignore the data.
return len(p), nil
}
func (l *DummyRWC) Close() error {
return nil
}
+1
View File
@@ -36,6 +36,7 @@ const (
eventLog = "/sys/kernel/security/tpm0/binary_bios_measurements"
Nonce = 32
PCR15 = 15
PCR16 = 16
Hash1 = 20
Hash256 = 32
Hash384 = 48