Skip to content

Commit

Permalink
flatten the new API to just tpm2 (#308)
Browse files Browse the repository at this point in the history
Merge all of the old TPMDirect libraries together into tpm2. That includes helpers, KDFs, etc., as well as the commands and structures. This was necessary to avoid dependency cycles, and it probably makes for an easier developer experience anyway.

This change adds a couple exceptions to the linting tool:

* tpm2.TPM2BXyz unfortunately stutters a bit, that's the tradeoff
* Startup_ and Shutdown_ end with an underscore until we can get a release of go-tpm-tools with a simulator that links to the legacy API at its new path

Fixes #302
  • Loading branch information
chrisfenner authored Sep 4, 2022
1 parent 7185bd0 commit b827cbb
Show file tree
Hide file tree
Showing 53 changed files with 1,546 additions and 3,023 deletions.
2 changes: 2 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ lint_task:
-E misspell
-E revive
--exclude-use-default=false
--exclude stutters
--exclude underscores
--max-same-issues=0
--max-issues-per-linter=0
./tpmutil/...
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ RUN apt-get update && apt-get install -y \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# We need golangci-lint for linting
ARG VERSION=1.41.1
ARG VERSION=1.49.0
RUN curl -SL \
https://github.com/golangci/golangci-lint/releases/download/v${VERSION}/golangci-lint-${VERSION}-linux-amd64.tar.gz \
--output golangci.tar.gz \
Expand Down
5 changes: 2 additions & 3 deletions legacy/tpm2/credactivation/credential_activation.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"io"

"github.com/google/go-tpm/legacy/tpm2"
"github.com/google/go-tpm/tpm2/helpers"
"github.com/google/go-tpm/tpmutil"
)

Expand Down Expand Up @@ -92,7 +91,7 @@ func generateRSA(aik *tpm2.HashValue, pub *rsa.PublicKey, symBlockSize int, secr
if err != nil {
return nil, nil, fmt.Errorf("generating symmetric key: %v", err)
}
symmetricKey := helpers.KDFaHash(h, seed, labelStorage, aikNameEncoded, nil, len(seed)*8)
symmetricKey := tpm2.KDFaHash(h, seed, labelStorage, aikNameEncoded, nil, len(seed)*8)
c, err := aes.NewCipher(symmetricKey)
if err != nil {
return nil, nil, fmt.Errorf("symmetric cipher setup: %v", err)
Expand All @@ -109,7 +108,7 @@ func generateRSA(aik *tpm2.HashValue, pub *rsa.PublicKey, symBlockSize int, secr
// Generate the integrity HMAC, which is used to protect the integrity of the
// encrypted structure.
// See section 24.5 of the TPM specification revision 2 part 1.
macKey := helpers.KDFaHash(h, seed, labelIntegrity, nil, nil, crypothash.Size()*8)
macKey := tpm2.KDFaHash(h, seed, labelIntegrity, nil, nil, crypothash.Size()*8)

mac := hmac.New(crypothash.New, macKey)
mac.Write(encIdentity)
Expand Down
72 changes: 69 additions & 3 deletions legacy/tpm2/kdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
package tpm2

import (
"github.com/google/go-tpm/tpm2/helpers"
"crypto"
"crypto/hmac"
"encoding/binary"
"hash"
)

// KDFa implements TPM 2.0's default key derivation function, as defined in
Expand All @@ -30,7 +33,7 @@ func KDFa(hashAlg Algorithm, key []byte, label string, contextU, contextV []byte
if err != nil {
return nil, err
}
return helpers.KDFaHash(h, key, label, contextU, contextV, bits), nil
return KDFaHash(h, key, label, contextU, contextV, bits), nil
}

// KDFe implements TPM 2.0's ECDH key derivation function, as defined in
Expand All @@ -46,5 +49,68 @@ func KDFe(hashAlg Algorithm, z []byte, use string, partyUInfo, partyVInfo []byte
if err != nil {
return nil, err
}
return helpers.KDFeHash(h, z, use, partyUInfo, partyVInfo, bits), nil
return KDFeHash(h, z, use, partyUInfo, partyVInfo, bits), nil
}

// KDFaHash implements TPM 2.0's default key derivation function, as defined in
// section 11.4.9.2 of the TPM revision 2 specification part 1.
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
// The key & label parameters must not be zero length.
// The label parameter is a non-null-terminated string.
// The contextU & contextV parameters are optional.
func KDFaHash(h crypto.Hash, key []byte, label string, contextU, contextV []byte, bits int) []byte {
mac := hmac.New(h.New, key)

out := kdf(mac, bits, func() {
mac.Write([]byte(label))
mac.Write([]byte{0}) // Terminating null character for C-string.
mac.Write(contextU)
mac.Write(contextV)
binary.Write(mac, binary.BigEndian, uint32(bits))
})
return out
}

// KDFeHash implements TPM 2.0's ECDH key derivation function, as defined in
// section 11.4.9.3 of the TPM revision 2 specification part 1.
// See: https://trustedcomputinggroup.org/resource/tpm-library-specification/
// The z parameter is the x coordinate of one party's private ECC key multiplied
// by the other party's public ECC point.
// The use parameter is a non-null-terminated string.
// The partyUInfo and partyVInfo are the x coordinates of the initiator's and
// the responder's ECC points, respectively.
func KDFeHash(h crypto.Hash, z []byte, use string, partyUInfo, partyVInfo []byte, bits int) []byte {
hash := h.New()

out := kdf(hash, bits, func() {
hash.Write(z)
hash.Write([]byte(use))
hash.Write([]byte{0}) // Terminating null character for C-string.
hash.Write(partyUInfo)
hash.Write(partyVInfo)
})
return out
}

func kdf(h hash.Hash, bits int, update func()) []byte {
bytes := (bits + 7) / 8
out := []byte{}

for counter := 1; len(out) < bytes; counter++ {
h.Reset()
binary.Write(h, binary.BigEndian, uint32(counter))
update()

out = h.Sum(out)
}
// out's length is a multiple of hash size, so there will be excess
// bytes if bytes isn't a multiple of hash size.
out = out[:bytes]

// As mentioned in the KDFa and KDFe specs mentioned above,
// the unused bits of the most significant octet are masked off.
if maskBits := uint8(bits % 8); maskBits > 0 {
out[0] &= (1 << maskBits) - 1
}
return out
}
13 changes: 5 additions & 8 deletions tpm2/commands/audit.go → tpm2/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ import (
"bytes"
"fmt"
"reflect"

"github.com/google/go-tpm/tpm2/structures/tpm"
"github.com/google/go-tpm/tpm2/structures/tpmi"
)

// CommandAudit represents an audit session for attesting the execution of a
// series of commands in the TPM. It is useful for both command and session
// auditing.
type CommandAudit struct {
hash tpmi.AlgHash
hash TPMIAlgHash
digest []byte
}

// NewAudit initializes a new CommandAudit with the specified hash algorithm.
func NewAudit(hash tpmi.AlgHash) (*CommandAudit, error) {
func NewAudit(hash TPMIAlgHash) (*CommandAudit, error) {
h, err := hash.Hash()
if err != nil {
return nil, err
Expand Down Expand Up @@ -59,7 +56,7 @@ func (a *CommandAudit) Digest() []byte {
// auditCPHash calculates the command parameter hash for a given command with
// the given hash algorithm. The command is assumed to not have any decrypt
// sessions.
func auditCPHash(h tpmi.AlgHash, c Command) ([]byte, error) {
func auditCPHash(h TPMIAlgHash, c Command) ([]byte, error) {
cc := c.Command()
names, err := cmdNames(c)
if err != nil {
Expand All @@ -75,7 +72,7 @@ func auditCPHash(h tpmi.AlgHash, c Command) ([]byte, error) {
// auditRPHash calculates the response parameter hash for a given response with
// the given hash algorithm. The command is assumed to be successful and to not
// have any encrypt sessions.
func auditRPHash(h tpmi.AlgHash, r Response) ([]byte, error) {
func auditRPHash(h TPMIAlgHash, r Response) ([]byte, error) {
cc := r.Response()
var parms bytes.Buffer
parameters := taggedMembers(reflect.ValueOf(r).Elem(), "handle", true)
Expand All @@ -84,5 +81,5 @@ func auditRPHash(h tpmi.AlgHash, r Response) ([]byte, error) {
return nil, fmt.Errorf("marshalling parameter %v: %w", i, err)
}
}
return rpHash(h, tpm.RCSuccess, cc, parms.Bytes())
return rpHash(h, TPMRCSuccess, cc, parms.Bytes())
}
2 changes: 1 addition & 1 deletion tpm2/structures/internal/bitfield.go → tpm2/bitfield.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package tpm2

import (
"fmt"
Expand Down
171 changes: 0 additions & 171 deletions tpm2/commands/create_loaded_test.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package tpm2

import (

Expand Down
10 changes: 3 additions & 7 deletions tpm2/helpers/crypto.go → tpm2/crypto.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
// Package helpers provides helper functionality for interacting with the TPM 2.0 API.
package helpers
package tpm2

import (
"crypto/elliptic"
"crypto/rsa"
"math/big"

"github.com/google/go-tpm/tpm2/structures/tpm2b"
"github.com/google/go-tpm/tpm2/structures/tpms"
)

// RSAPub converts a TPM RSA public key into one recognized by the rsa package.
func RSAPub(parms *tpms.RSAParms, pub *tpm2b.PublicKeyRSA) (*rsa.PublicKey, error) {
func RSAPub(parms *TPMSRSAParms, pub *TPM2BPublicKeyRSA) (*rsa.PublicKey, error) {
result := rsa.PublicKey{
N: big.NewInt(0).SetBytes(pub.Buffer),
E: int(parms.Exponent),
Expand All @@ -34,7 +30,7 @@ type ECDHPub struct {

// ECCPub converts a TPM ECC public key into one recognized by the elliptic
// package's point-multiplication functions, for use in ECDH.
func ECCPub(parms *tpms.ECCParms, pub *tpms.ECCPoint) (*ECDHPub, error) {
func ECCPub(parms *TPMSECCParms, pub *TPMSECCPoint) (*ECDHPub, error) {
curve, err := parms.CurveID.Curve()
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit b827cbb

Please sign in to comment.