Skip to content

Commit

Permalink
TPM2: Added CertifyEx and encodeCertifyEx (#211)
Browse files Browse the repository at this point in the history
* TPM2: Added CertifyEx and encodeCertifyEx which differ from Certify and encodeCertify in that they take the scheme to be used as an additional argument.

Signed-off-by: El Mostafa IDRASSI <[email protected]>

* Fixed typo

* Rename parentAuth and ownerAuth to objectAuth and signerAuth respectively.

Signed-off-by: El Mostafa IDRASSI <[email protected]>

* Update Certify documentation to explain it makes use of the hardcoded signing scheme {AlgRSASSA, AlgSHA256}.

* Pack AlgNull with no following hash alg in case of AlgNull scheme, and add TODO comment.

* Comment formatting and other requested changes.

Signed-off-by: El Mostafa IDRASSI <[email protected]>

* Replace all occurrences of tpmtSigScheme with SigScheme.
Add CertifyEx tests for both RSASSA/SHA256 and ALG_NULL cases.

* Better implementation of TestCertifyEx with all cases.

Signed-off-by: El Mostafa IDRASSI <[email protected]>

* Requested changes implemented.
  • Loading branch information
ElMostafaIdrassi authored Oct 13, 2020
1 parent ad82e86 commit 6aef8a0
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 15 deletions.
5 changes: 0 additions & 5 deletions tpm2/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,11 +619,6 @@ func (p Private) Encode() ([]byte, error) {
return tpmutil.Pack(p)
}

type tpmtSigScheme struct {
Scheme Algorithm
Hash Algorithm
}

// AttestationData contains data attested by TPM commands (like Certify).
type AttestationData struct {
Magic uint32
Expand Down
55 changes: 55 additions & 0 deletions tpm2/test/tpm2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,61 @@ func TestCertify(t *testing.T) {
})
}

func TestCertifyEx(t *testing.T) {
rw := openTPM(t)
defer rw.Close()

restrictedKeySignerFlags := FlagSignerDefault
unrestrictedKeySignerFlags := FlagSign | FlagFixedTPM | FlagFixedParent | FlagSensitiveDataOrigin | FlagUserWithAuth
testCases := []struct {
description string
attributes KeyProp
keyScheme SigScheme
passedScheme SigScheme
shouldPass bool
}{
{"Null-SHA1", unrestrictedKeySignerFlags, SigScheme{Alg: AlgNull}, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA1}, true},
{"Null-SHA256", unrestrictedKeySignerFlags, SigScheme{Alg: AlgNull}, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}, true},
{"Null-Null", unrestrictedKeySignerFlags, SigScheme{Alg: AlgNull}, SigScheme{Alg: AlgNull}, false},
{"SHA256-Null", restrictedKeySignerFlags, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}, SigScheme{Alg: AlgNull}, true},
{"SHA256-SHA256", restrictedKeySignerFlags, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}, true},
{"SHA256-SHA1", restrictedKeySignerFlags, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}, SigScheme{Alg: AlgRSASSA, Hash: AlgSHA1}, false},
}

for _, testCase := range testCases {
params := Public{
Type: AlgRSA,
NameAlg: AlgSHA256,
Attributes: testCase.attributes,
RSAParameters: &RSAParams{
Sign: &testCase.keyScheme,
KeyBits: 2048,
},
}

t.Run(testCase.description, func(t *testing.T) {
signerHandle, _, err := CreatePrimary(rw, HandleOwner, PCRSelection{}, emptyPassword, defaultPassword, params)
if err != nil {
t.Fatalf("CreatePrimary(signer) failed: %s", err)
}
defer FlushContext(rw, signerHandle)

subjectHandle, _, err := CreatePrimary(rw, HandlePlatform, PCRSelection{}, emptyPassword, defaultPassword, params)
if err != nil {
t.Fatalf("CreatePrimary(subject) failed: %s", err)
}
defer FlushContext(rw, subjectHandle)

_, _, err = CertifyEx(rw, defaultPassword, defaultPassword, subjectHandle, signerHandle, nil, testCase.passedScheme)
if err != nil && testCase.shouldPass {
t.Errorf("CertifyEx expected to succeed but failed: %s", err)
} else if err == nil && !testCase.shouldPass {
t.Errorf("CertifyEx expected to fail but succeeded")
}
})
}
}

func TestCertifyExternalKey(t *testing.T) {
rw := openTPM(t)
defer rw.Close()
Expand Down
65 changes: 55 additions & 10 deletions tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -1550,24 +1550,51 @@ func Sign(rw io.ReadWriter, key tpmutil.Handle, password string, digest []byte,
return SignWithSession(rw, HandlePasswordSession, key, password, digest, validation, sigScheme)
}

func encodeCertify(parentAuth, ownerAuth string, object, signer tpmutil.Handle, qualifyingData tpmutil.U16Bytes) ([]byte, error) {
func encodeCertify(objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData tpmutil.U16Bytes) ([]byte, error) {
ha, err := tpmutil.Pack(object, signer)
if err != nil {
return nil, err
}

auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentAuth)}, AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(ownerAuth)})
auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(objectAuth)}, AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(signerAuth)})
if err != nil {
return nil, err
}

scheme := tpmtSigScheme{AlgRSASSA, AlgSHA256}
scheme := SigScheme{Alg: AlgRSASSA, Hash: AlgSHA256}
// Use signing key's scheme.
params, err := tpmutil.Pack(qualifyingData, scheme)
s, err := scheme.encode()
if err != nil {
return nil, err
}
return concat(ha, auth, params)
data, err := tpmutil.Pack(qualifyingData)
if err != nil {
return nil, err
}
return concat(ha, auth, data, s)
}

// This function differs from encodeCertify in that it takes the scheme to be used as an additional argument.
func encodeCertifyEx(objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData tpmutil.U16Bytes, scheme SigScheme) ([]byte, error) {
ha, err := tpmutil.Pack(object, signer)
if err != nil {
return nil, err
}

auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(objectAuth)}, AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(signerAuth)})
if err != nil {
return nil, err
}

s, err := scheme.encode()
if err != nil {
return nil, err
}
data, err := tpmutil.Pack(qualifyingData)
if err != nil {
return nil, err
}
return concat(ha, auth, data, s)
}

func decodeCertify(resp []byte) ([]byte, []byte, error) {
Expand Down Expand Up @@ -1604,14 +1631,32 @@ func decodeCertify(resp []byte) ([]byte, []byte, error) {
}

// Certify generates a signature of a loaded TPM object with a signing key
// signer. Returned values are: attestation data (TPMS_ATTEST), signature and
// error, if any.
func Certify(rw io.ReadWriter, parentAuth, ownerAuth string, object, signer tpmutil.Handle, qualifyingData []byte) ([]byte, []byte, error) {
Cmd, err := encodeCertify(parentAuth, ownerAuth, object, signer, qualifyingData)
// signer. This function calls encodeCertify which makes use of the hardcoded
// signing scheme {AlgRSASSA, AlgSHA256}. Returned values are: attestation data (TPMS_ATTEST),
// signature and error, if any.
func Certify(rw io.ReadWriter, objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData []byte) ([]byte, []byte, error) {
cmd, err := encodeCertify(objectAuth, signerAuth, object, signer, qualifyingData)
if err != nil {
return nil, nil, err
}
resp, err := runCommand(rw, TagSessions, CmdCertify, tpmutil.RawBytes(cmd))
if err != nil {
return nil, nil, err
}
return decodeCertify(resp)
}

// CertifyEx generates a signature of a loaded TPM object with a signing key
// signer. This function differs from Certify in that it takes the scheme
// to be used as an additional argument and calls encodeCertifyEx instead
// of encodeCertify. Returned values are: attestation data (TPMS_ATTEST),
// signature and error, if any.
func CertifyEx(rw io.ReadWriter, objectAuth, signerAuth string, object, signer tpmutil.Handle, qualifyingData []byte, scheme SigScheme) ([]byte, []byte, error) {
cmd, err := encodeCertifyEx(objectAuth, signerAuth, object, signer, qualifyingData, scheme)
if err != nil {
return nil, nil, err
}
resp, err := runCommand(rw, TagSessions, CmdCertify, tpmutil.RawBytes(Cmd))
resp, err := runCommand(rw, TagSessions, CmdCertify, tpmutil.RawBytes(cmd))
if err != nil {
return nil, nil, err
}
Expand Down

0 comments on commit 6aef8a0

Please sign in to comment.