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

Using TPM key ctx file created with TPM2 Tools to sign data #378

Open
athomas97 opened this issue Nov 29, 2024 · 0 comments
Open

Using TPM key ctx file created with TPM2 Tools to sign data #378

athomas97 opened this issue Nov 29, 2024 · 0 comments

Comments

@athomas97
Copy link

Is it possible to use a primary key's ctx file (created with tpm2-tools) to sign some data using the "github.com/google/go-tpm/tpm2" package. Im using tpm2 and am on an ubuntu linux VM.

I'm using these commands to create the key in the terminal. Im creating the key as a transient object, rather than saving it to a persistent handle.

echo -n -e "\x00\x01\x49\x44\x45\x56\x49\x44" > idevid.dat
tpm2_createprimary --hierarchy e --key-algorithm rsa2048 --attributes "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|sign|noda" --key-context idevid.ctx --unique-data idevid.dat --output idevid.pub

I am able to sign data with idevid.ctx key created above with the following tpm2 tools commands

echo "my message" > message.dat
tpm2_sign --key-context idevid.ctx --hash-algorithm sha256 --signature sig.rssa message.dat
tpm2_verifysignature --key-context idevid.ctx --hash-algorithm sha256 --signature sig.rssa --message message.dat

Im making a connection to the TPM using the "github.com/google/go-tpm/tpm2/transport" package

tpmDevice := "/dev/tpmrm0"
tpm, err := transport.OpenTPM(tpmDevice)
if err != nil {
	fmt.Printf("Could not connect to TPM: %v", err)
}

Im currently having an issue trying to load the key handle of the idevid.ctx file into the KeyHandle field in the Sign struct. The examples I have seen in the go-tpm repo seem to make the keys using go-tpm with functions like CreatePrimary and then pass the key handle returned by CreatePrimary into other functions like Sign. In my case I need to get the key handle object by loading an external idevid.ctx file. Below an example of code that im building off of to sign data.

sign := Sign{
	KeyHandle: NamedHandle{
		Handle: handle,
		Name:   name,
	},
	Digest: TPM2BDigest{
		Buffer: digest[:],
	},
	InScheme: TPMTSigScheme{
		Scheme: TPMAlgRSASSA,
		Details: NewTPMUSigScheme(
			TPMAlgRSASSA,
			&TPMSSchemeHash{
				HashAlg: TPMAlgSHA256,
			},
		),
	},
	Validation: TPMTTKHashCheck{
		Tag: TPMSTHashCheck,
	},
}
rspSign, err := sign.Execute(tpm)
if err != nil {
	fmt.Printf("Failed to Sign Digest: %v", err)
}
fmt.Println(rspSign)

I wrote the following code to decode the ctx file and load its contents into a TPMSContext object. Using the tpm2-tools tpm2_print command, Ive been able to confirm that the value of the savehandle, hierarchy, sequence and contextblob size are correct and that they are the correct type. I have not been able to verify if the value of contextblob is correct.

var ctx TPMSContext
reader := bytes.NewReader(primaryCtx)
var extra uint64
if err := binary.Read(reader, binary.BigEndian, &extra); err != nil {
	fmt.Printf("Failed to parse SavedHandle: %v", err)
}
if err := binary.Read(reader, binary.BigEndian, &ctx.Hierarchy); err != nil {
	fmt.Printf("Failed to parse SavedHandle: %v", err)
}
if err := binary.Read(reader, binary.BigEndian, &ctx.SavedHandle); err != nil {
	fmt.Printf("Failed to parse Hierarchy: %v", err)
}
if err := binary.Read(reader, binary.BigEndian, &ctx.Sequence); err != nil {
	fmt.Printf("Failed to parse size: %v", err)
}		
var size uint16
if err := binary.Read(reader, binary.BigEndian, &size); err != nil {
	fmt.Printf("Failed to parse size: %v", err)
}
contextData := make([]byte, size)
if err := binary.Read(reader, binary.BigEndian, &contextData); err != nil {
	fmt.Printf("Failed to read context data buffer: %v", err)
	return
}
ctx.ContextBlob = TPM2BContextData{
	Buffer: contextData,
}

I have tried directly loading the ctx.SavedHandle variable (which is type TPMHandle) and I tried using the KnownName function on it to get the name and then pass the handle and name value into the NamedHandle object.

	name := ctx.SavedHandle.KnownName()

	digest := sha256.Sum256([]byte("migrationpains"))	
	sign := Sign{
		KeyHandle: NamedHandle{
			Handle: ctx.SavedHandle,
			Name:   *name,
		},
		Digest: TPM2BDigest{
			Buffer: digest[:],
		},
		InScheme: TPMTSigScheme{
			Scheme: TPMAlgRSASSA,
			Details: NewTPMUSigScheme(
				TPMAlgRSASSA,
				&TPMSSchemeHash{
					HashAlg: TPMAlgSHA256,
				},
			),
		},
		Validation: TPMTTKHashCheck{
			Tag: TPMSTHashCheck,
		},
	}
	rspSign, err := sign.Execute(tpm)
	if err != nil {
		fmt.Printf("Failed to Sign Digest: %v", err)
	}
}

It seems that the value returned by ctx.SaveHandle.KnownName() is nil. So when I run the code above I get the following error

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x525ac8]

I have also tried to use the ContextLoad function to get the key handle from the idevid.ctx file to pass into the Sign struct

	var ctx TPMSContext
	reader := bytes.NewReader(primaryCtx)
	var extra uint64
	if err := binary.Read(reader, binary.BigEndian, &extra); err != nil {
		fmt.Printf("Failed to parse SavedHandle: %v", err)
	}
	if err := binary.Read(reader, binary.BigEndian, &ctx.Hierarchy); err != nil {
		fmt.Printf("Failed to parse SavedHandle: %v", err)
	}
	if err := binary.Read(reader, binary.BigEndian, &ctx.SavedHandle); err != nil {
		fmt.Printf("Failed to parse Hierarchy: %v", err)
	}
	if err := binary.Read(reader, binary.BigEndian, &ctx.Sequence); err != nil {
		fmt.Printf("Failed to parse size: %v", err)
	}		
	var size uint16
	if err := binary.Read(reader, binary.BigEndian, &size); err != nil {
		fmt.Printf("Failed to parse size: %v", err)
	}
	contextData := make([]byte, size)
	if err := binary.Read(reader, binary.BigEndian, &contextData); err != nil {
		fmt.Printf("Failed to read context data buffer: %v", err)
		return
	}
	ctx.ContextBlob = TPM2BContextData{
		Buffer: contextData,
	}	
	contextLoad := ContextLoad{
		Context: ctx,
	}

	rspCL, err := contextLoad.Execute(tpm)
	if err != nil {
		fmt.Printf("ContextLoad failed: %v", err)
	}
	fmt.Println(rspCL)
}

When I run the code above to load the context I get the following error.

ContextLoad failed: TPM_RC_SIZE (parameter 1): structure is the wrong size<nil>

Is there a way that I can load the idevid.ctx file and use go-tpm to sign data?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant