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

Implement TPM2_Commit #296

Merged
merged 36 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6170d54
Define the structure of ECDAA params
akakou Jul 1, 2022
e431e71
Fix section number of TPMI_ALG_KEYEDHASH_SCHEME
akakou Jul 1, 2022
6b6b2d0
Add type alias for internal.TPMSSchemeECDAA as tpms.SchemeECDAA
akakou Jul 1, 2022
4425b52
Merge branch 'tpmdirect' into ecdaa-structure
akakou Jul 1, 2022
0d09135
Fix the mistake in the name of TPMSSchemeECDAA
akakou Jul 3, 2022
1058dc0
Implement TPM2_Commit
akakou Jul 5, 2022
142b913
Create a primary key for the test of TPM2_Commit
akakou Jul 5, 2022
c0c0e92
Define the signing scheme for ECDAA
akakou Jul 5, 2022
b98a1ab
Create a key for the test of TPM2_Commit
akakou Jul 5, 2022
bf62168
Define structures of ECCPoint.
akakou Jul 8, 2022
b3e8801
Update the commit command to use tpm2b parameters
akakou Jul 8, 2022
d56f2ed
Use TPM2_CreateLoaded on the tests of TPM2_Commit
akakou Jul 8, 2022
dafdbfe
Implement the test calling TPM2_Commit (WIP)
akakou Jul 8, 2022
078c4e9
Fix space added mistakenly on annotation
akakou Jul 10, 2022
928a275
Fix the type of out private
akakou Jul 12, 2022
dcaa3b9
Create a new key when the test commit
akakou Jul 12, 2022
98f3f77
Add sized type annotation to the TPM2BECCPoint
akakou Jul 13, 2022
f4b163f
Fix the response type of ECC Point
akakou Jul 13, 2022
53f5404
Set the BN256 generator to the P1
akakou Jul 13, 2022
1222821
Remove the count from the request of TPM2_Commit
akakou Jul 26, 2022
0184e2b
Add closing defer to the simulator
akakou Jul 26, 2022
1bb1439
Merge branch 'tpmdirect' into tpm2-commit
akakou Jul 26, 2022
c35e6b7
Rename the count of commit response to counter
akakou Jul 26, 2022
093804b
Add comments for some parameters related to commit
akakou Jul 26, 2022
7a7c962
Add flush context for the primary key
akakou Jul 26, 2022
927ced6
Fix mistaken subject of comment
akakou Jul 26, 2022
7a8d643
Merge branch 'tpm2-commit' of github.com:akakou/go-tpm into tpm2-commit
akakou Jul 26, 2022
a927c83
Fix typo (Conter => Counter)
akakou Jul 26, 2022
072b18e
Merge branch 'tpmdirect' into tpm2-commit
akakou Jul 29, 2022
8f05bd9
Merge branch 'tpmdirect' into tpm2-commit
akakou Aug 4, 2022
4199ab2
Merge branch 'tpmdirect' into tpm2-commit
akakou Aug 13, 2022
5d362af
Use only the primary key for the TPM2_Commit test
akakou Aug 15, 2022
be6eae0
Omit setting commit count
akakou Aug 15, 2022
53246a5
Use sha256, not sha1
akakou Aug 15, 2022
e5d3f9a
Define deferred flush right after created
akakou Aug 15, 2022
9babf4c
Check that the counter was incremented on the test
akakou Aug 15, 2022
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
20 changes: 16 additions & 4 deletions direct/structures/internal/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -1101,13 +1101,18 @@ type TPMSSigSchemeRSAPSS TPMSSchemeHash
// See definition in Part 2: Structures, section 11.2.1.3.
type TPMSSigSchemeECDSA TPMSSchemeHash

// TPMSSigSchemeECDAA represents a TPMS_SIG_SCHEME_ECDAA.
// See definition in Part 2: Structures, section 11.2.1.3.
type TPMSSigSchemeECDAA TPMSSchemeECDAA

// TPMUSigScheme represents a TPMU_SIG_SCHEME.
// See definition in Part 2: Structures, section 11.2.1.4.
type TPMUSigScheme struct {
HMAC *TPMSSchemeHMAC `gotpm:"selector=0x0005"` // TPM_ALG_HMAC
RSASSA *TPMSSchemeHash `gotpm:"selector=0x0014"` // TPM_ALG_RSASSA
RSAPSS *TPMSSchemeHash `gotpm:"selector=0x0016"` // TPM_ALG_RSAPSS
ECDSA *TPMSSchemeHash `gotpm:"selector=0x0018"` // TPM_ALG_ECDSA
HMAC *TPMSSchemeHMAC `gotpm:"selector=0x0005"` // TPM_ALG_HMAC
RSASSA *TPMSSchemeHash `gotpm:"selector=0x0014"` // TPM_ALG_RSASSA
RSAPSS *TPMSSchemeHash `gotpm:"selector=0x0016"` // TPM_ALG_RSAPSS
ECDSA *TPMSSchemeHash `gotpm:"selector=0x0018"` // TPM_ALG_ECDSA
ECDAA *TPMSSchemeECDAA `gotpm:"selector=0x001a"` // TPM_ALG_ECDAA
}

// TPMTSigScheme represents a TPMT_SIG_SCHEME.
Expand Down Expand Up @@ -1178,6 +1183,7 @@ type TPMUAsymScheme struct {
OAEP *TPMSEncSchemeOAEP `gotpm:"selector=0x0017"` // TPM_ALG_OAEP
ECDSA *TPMSSigSchemeECDSA `gotpm:"selector=0x0018"` // TPM_ALG_ECDSA
ECDH *TPMSKeySchemeECDH `gotpm:"selector=0x0019"` // TPM_ALG_ECDH
ECDAA *TPMSSigSchemeECDAA `gotpm:"selector=0x001a"` // TPM_ALG_ECDAA
}

// TPMIAlgRSAScheme represents a TPMI_ALG_RSA_SCHEME.
Expand Down Expand Up @@ -1218,6 +1224,12 @@ type TPMSECCPoint struct {
Y TPM2BECCParameter
}

// TPM2BECCPoint represents a TPM2B_ECC_POINT.
// See definition in Part 2: Structures, section 11.2.5.3.
type TPM2BECCPoint struct {
Point TPMSECCPoint `gotpm:"sized"`
}

// TPMIAlgECCScheme represents a TPMI_ALG_ECC_SCHEME.
// See definition in Part 2: Structures, section 11.2.5.4.
type TPMIAlgECCScheme = TPMAlgID
Expand Down
4 changes: 4 additions & 0 deletions direct/structures/tpm2b/tpm2b.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ type PrivateKeyRSA = internal.TPM2BPrivateKeyRSA
// See definition in Part 2: Structures, section 11.2.5.1.
type ECCParameter = internal.TPM2BECCParameter

// ECCPoint represents a TPM2B_ECC_POINT.
// See definition in Part 2: Structures, section 11.2.5.3
type ECCPoint = internal.TPM2BECCPoint

// EncryptedSecret represents a TPM2B_ENCRYPTED_SECRET.
// See definition in Part 2: Structures, section 11.4.33.
type EncryptedSecret = internal.TPM2BEncryptedSecret
Expand Down
4 changes: 4 additions & 0 deletions direct/structures/tpms/tpms.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ type SigSchemeRSAPSS = internal.TPMSSigSchemeRSAPSS
// See definition in Part 2: Structures, section 11.2.1.3.
type SigSchemeECDSA = internal.TPMSSigSchemeECDSA

// SigSchemeECDAA represents a TPMS_SIG_SCHEME_ECDAA.
// See definition in Part 2: Structures, section 11.2.1.3.
type SigSchemeECDAA = internal.TPMSSigSchemeECDAA

// EncSchemeRSAES represents a TPMS_ENC_SCHEME_RSAES.
// See definition in Part 2: Structures, section 11.2.2.2.
type EncSchemeRSAES = internal.TPMSEncSchemeRSAES
Expand Down
160 changes: 160 additions & 0 deletions direct/tpm2/commit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package tpm2

import (
"testing"

"github.com/google/go-tpm/direct/helpers"
"github.com/google/go-tpm/direct/structures/tpm"
"github.com/google/go-tpm/direct/structures/tpm2b"
"github.com/google/go-tpm/direct/structures/tpma"
"github.com/google/go-tpm/direct/structures/tpms"
"github.com/google/go-tpm/direct/structures/tpmt"
"github.com/google/go-tpm/direct/structures/tpmu"
"github.com/google/go-tpm/direct/transport/simulator"
)

func TestCommit(t *testing.T) {
thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}

defer thetpm.Close()

password := []byte("hello")

primary := CreateLoaded{
akakou marked this conversation as resolved.
Show resolved Hide resolved
ParentHandle: tpm.RHEndorsement,
InSensitive: tpm2b.SensitiveCreate{
Sensitive: tpms.SensitiveCreate{
UserAuth: tpm2b.Auth{
Buffer: password,
},
},
},
InPublic: tpm2b.Template{
Template: tpmt.Public{
Type: tpm.AlgECC,
NameAlg: tpm.AlgSHA1,
ObjectAttributes: tpma.Object{
FixedTPM: true,
FixedParent: true,
SensitiveDataOrigin: true,
UserWithAuth: true,
Decrypt: true,
Restricted: true,
},
Parameters: tpmu.PublicParms{
ECCDetail: &tpms.ECCParms{
Symmetric: tpmt.SymDefObject{
Algorithm: tpm.AlgAES,
KeyBits: tpmu.SymKeyBits{
AES: helpers.NewKeyBits(128),
},
Mode: tpmu.SymMode{
AES: helpers.NewAlgID(tpm.AlgCFB),
},
},
CurveID: tpm.ECCNistP256,
KDF: tpmt.KDFScheme{
Scheme: tpm.AlgNull,
},
},
},
},
},
}

rspCP, err := primary.Execute(thetpm)
akakou marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
t.Fatalf("could not create key: %v", err)
}

create := CreateLoaded{
ParentHandle: AuthHandle{
Handle: rspCP.ObjectHandle,
Name: rspCP.Name,
Auth: PasswordAuth(password),
},
InSensitive: tpm2b.SensitiveCreate{
Sensitive: tpms.SensitiveCreate{
UserAuth: tpm2b.Auth{
Buffer: password,
},
},
},
InPublic: tpm2b.Template{
Template: tpmt.Public{
Type: tpm.AlgECC,
NameAlg: tpm.AlgSHA1,
ObjectAttributes: tpma.Object{
FixedTPM: true,
FixedParent: true,
UserWithAuth: true,
SensitiveDataOrigin: true,
SignEncrypt: true,
},
Parameters: tpmu.PublicParms{
ECCDetail: &tpms.ECCParms{
Symmetric: tpmt.SymDefObject{
Algorithm: tpm.AlgNull,
},
Scheme: tpmt.ECCScheme{
Scheme: tpm.AlgECDAA,
Details: tpmu.AsymScheme{
ECDAA: &tpms.SigSchemeECDAA{
HashAlg: tpm.AlgSHA1,
akakou marked this conversation as resolved.
Show resolved Hide resolved
Count: 1,
akakou marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
CurveID: tpm.ECCBNP256,
KDF: tpmt.KDFScheme{
Scheme: tpm.AlgNull,
},
},
},
},
},
}

rspC, err := create.Execute(thetpm)
if err != nil {
t.Fatalf("could not create key: %v", err)
}

commit := Commit{
SignHandle: AuthHandle{
Handle: rspC.ObjectHandle,
Name: rspC.Name,
Auth: PasswordAuth(password),
},
P1: tpm2b.ECCPoint{
Point: tpms.ECCPoint{
X: tpm2b.ECCParameter{
Buffer: []byte{1},
},
Y: tpm2b.ECCParameter{
Buffer: []byte{2},
},
},
},
S2: tpm2b.SensitiveData{
Buffer: []byte{},
},
Y2: tpm2b.ECCParameter{
Buffer: []byte{},
},
}

_, err = commit.Execute(thetpm)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing the output response with some off-tpm validation would be good here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Umm...Any good idea to test this output...?

I have just an idea that implements full ECDAA Setup/Join for this, but it's complex and we should avoid it.

Copy link
Contributor

@matt-tsai matt-tsai Jul 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @chrisfenner is a better person to discuss this with, however he is out at the moment and will be back next week. In the meantime, I will add him to be a reviewer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm new to ECDAA signing, but I think you should be able to use TPM2_Sign (which is already implemented) to produce an ECDAA signature using the commit value. You'll have to grab the commit counter from the Commit command and use it on the ECDAA scheme structure in the Sign command.

Bonus points: Call Sign again with the same counter value and expect it to fail :)

No need to validate the signature at this point, unless you really want to. I imagine that belongs as part of a larger body of ECDAA sample code that someone might work on (maybe you or someone else) as part of a separate effort.

if err != nil {
t.Fatalf("could not commit: %v", err)
}

flushContextCP := FlushContext{FlushHandle: rspCP.ObjectHandle}
akakou marked this conversation as resolved.
Show resolved Hide resolved
defer flushContextCP.Execute(thetpm)

flushContextC := FlushContext{FlushHandle: rspC.ObjectHandle}
defer flushContextC.Execute(thetpm)
}
43 changes: 42 additions & 1 deletion direct/tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ type CreateLoadedResponse struct {
// handle of type TPM_HT_TRANSIENT for loaded object
ObjectHandle tpm.Handle `gotpm:"handle"`
// the sensitive area of the object (optional)
OutPrivate *tpm2b.Private `gotpm:"optional"`
OutPrivate tpm2b.Private `gotpm:"optional"`
// the public portion of the created object
OutPublic tpm2b.Public
// the name of the created object
Expand Down Expand Up @@ -654,6 +654,47 @@ type GetSessionAuditDigestResponse struct {
// Response implements the Response interface.
func (*GetSessionAuditDigestResponse) Response() tpm.CC { return tpm.CCGetSessionAuditDigest }

// Commit is the input to TPM2_Commit.
// See definition in Part 3, Commands, section 19.2.
type Commit struct {
// handle of the key that will be used in the signing operation
SignHandle handle `gotpm:"handle,auth"`
// a point (M) on the curve used by signHandle
P1 tpm2b.ECCPoint
// octet array used to derive x-coordinate of a base point
S2 tpm2b.SensitiveData
// y coordinate of the point associated with s2
Y2 tpm2b.ECCParameter
}

// Command implements the Command interface.
func (*Commit) Command() tpm.CC { return tpm.CCCommit }

// Execute executes the command and returns the response.
func (cmd *Commit) Execute(t transport.TPM, s ...Session) (*CommitResponse, error) {
var rsp CommitResponse
if err := execute(t, cmd, &rsp, s...); err != nil {
return nil, err
}

return &rsp, nil
}

// CommitResponse is the response from TPM2_Commit.
type CommitResponse struct {
// ECC point K ≔ [ds](x2, y2)
K tpm2b.ECCPoint
// ECC point L ≔ [r](x2, y2)
L tpm2b.ECCPoint
// ECC point E ≔ [r]P1
E tpm2b.ECCPoint
// least-significant 16 bits of commitCount
Counter uint16
}

// Response implements the Response interface.
func (*CommitResponse) Response() tpm.CC { return tpm.CCCommit }

// VerifySignature is the input to TPM2_VerifySignature.
// See definition in Part 3, Commands, section 20.1
type VerifySignature struct {
Expand Down