-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Introduce Direct TPM2 API This commit introduces a new method of interacting with a TPM 2.0. Instead of plumbing each TPM API into one or more Go functions, this code defines structures for every TPM 2.0 command request and response. These map 1:1 with the actual command parameters comprehended by the TPM, so any invocation of any command is possible (once all the command structures are written). This commit introduces enough of the TPM 2.0 API surface to put together some interesting end-to-end tests, mostly around sealing. Another objective of the Direct API is to facilitate use of the TPM's session-based command transport features (e.g., audit and encryption sessions). See the test code for examples of how to easily use these APIs to, e.g., set up an EK-salted session for session-encrypted unseal. Change-Id: I1549dd596869d79ddd41ff3c5f9ffdadc9628ed4 * fix problems identified by go vet * fix some more issues identified by go vet * fix some more issues surfaced by vet * fix more go vet issues * one last round of go vet fixes * Use subpackages and put the Execute function on the command types (#1) * WIP: put stuff into subpackages to make the names nice * use internal monolithic package to avoid cycles * complete the tpm2 package * fix test references to renamed types * switch to command.Execute pattern * fix some unkeyed field values detected by go vet * stop panicking from Hash * Draft implementation of Joe's embedded-reserved-field bitwise solution * Turn command handles into an interface to avoid caller stuttering
- Loading branch information
1 parent
99c5a9b
commit 0b55c34
Showing
34 changed files
with
7,881 additions
and
51 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package helpers | ||
|
||
import ( | ||
"crypto/elliptic" | ||
"crypto/rsa" | ||
"math/big" | ||
|
||
"github.com/google/go-tpm/direct/structures/tpm2b" | ||
"github.com/google/go-tpm/direct/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) { | ||
result := rsa.PublicKey{ | ||
N: big.NewInt(0).SetBytes(pub.Buffer), | ||
E: int(parms.Exponent), | ||
} | ||
// TPM considers 65537 to be the default RSA public exponent, and 0 in | ||
// the parms | ||
// indicates so. | ||
if result.E == 0 { | ||
result.E = 65537 | ||
} | ||
return &result, nil | ||
} | ||
|
||
// ECDHPub is a convenience wrapper around the necessary info to perform point | ||
// multiplication with the elliptic package. | ||
type ECDHPub struct { | ||
Curve elliptic.Curve | ||
X, Y *big.Int | ||
} | ||
|
||
// 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) { | ||
curve, err := parms.CurveID.Curve() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &ECDHPub{ | ||
Curve: curve, | ||
X: big.NewInt(0).SetBytes(pub.X.Buffer), | ||
Y: big.NewInt(0).SetBytes(pub.Y.Buffer), | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package helpers | ||
|
||
import ( | ||
"encoding/binary" | ||
|
||
"github.com/google/go-tpm/direct/structures/tpm" | ||
) | ||
|
||
// PrimaryHandleName returns the TPM Name of a primary handle. | ||
func PrimaryHandleName(h tpm.Handle) []byte { | ||
result := make([]byte, 4) | ||
binary.BigEndian.PutUint32(result, uint32(h)) | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package helpers | ||
|
||
import "github.com/google/go-tpm/direct/structures/tpm" | ||
|
||
// This file provides wrapper functions for concrete types used by tpm2, for | ||
// setting union member pointers. | ||
|
||
// NewKeyBits allocates and returns the address of a new tpm.KeyBits. | ||
func NewKeyBits(v tpm.KeyBits) *tpm.KeyBits { return &v } | ||
|
||
// NewAlgID allocates and returns the address of a new tpm.AlgID. | ||
func NewAlgID(v tpm.AlgID) *tpm.AlgID { return &v } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package internal | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// Bitfield represents a TPM bitfield (i.e., TPMA_*) type. | ||
type Bitfield interface { | ||
// Length returns the length of the bitfield. | ||
Length() int | ||
} | ||
|
||
// BitGetter represents a TPM bitfield (i.e., TPMA_*) type that can be read. | ||
type BitGetter interface { | ||
Bitfield | ||
// GetReservedBit returns the value of the given reserved bit. | ||
// If the bit is not reserved, returns false. | ||
GetReservedBit(pos int) bool | ||
} | ||
|
||
// BitSetter represents a TPM bitfield (i.e., TPMA_*) type that can be written. | ||
type BitSetter interface { | ||
Bitfield | ||
// GetReservedBit sets the value of the given reserved bit. | ||
SetReservedBit(pos int, val bool) | ||
} | ||
|
||
func checkPos(pos int, len int) { | ||
if pos >= len || pos < 0 { | ||
panic(fmt.Errorf("bit %d out of range for %d-bit field", pos, len)) | ||
} | ||
} | ||
|
||
// bitfield8 represents an 8-bit bitfield which may have reserved bits. | ||
// 8-bit TPMA_* types embed this one, and the reserved bits are stored in it. | ||
type bitfield8 uint8 | ||
|
||
// Length implements the Bitfield interface. | ||
func (bitfield8) Length() int { | ||
return 8 | ||
} | ||
|
||
// GetReservedBit implements the BitGetter interface. | ||
func (r bitfield8) GetReservedBit(pos int) bool { | ||
checkPos(pos, 8) | ||
return r&(1<<pos) != 0 | ||
} | ||
|
||
// SetReservedBit implements the BitSetter interface. | ||
func (r *bitfield8) SetReservedBit(pos int, val bool) { | ||
checkPos(pos, 8) | ||
if val { | ||
*r |= 1 << pos | ||
} else { | ||
*r &= ^(1 << pos) | ||
} | ||
} | ||
|
||
// bitfield32 represents a 32-bit bitfield which may have reserved bits. | ||
// 32-bit TPMA_* types embed this one, and the reserved bits are stored in it. | ||
type bitfield32 uint32 | ||
|
||
// Length implements the Bitfield interface. | ||
func (bitfield32) Length() int { | ||
return 32 | ||
} | ||
|
||
// GetReservedBit implements the BitGetter interface. | ||
func (r bitfield32) GetReservedBit(pos int) bool { | ||
checkPos(pos, 32) | ||
return r&(1<<pos) != 0 | ||
} | ||
|
||
// SetReservedBit implements the BitSetter interface. | ||
func (r *bitfield32) SetReservedBit(pos int, val bool) { | ||
checkPos(pos, 32) | ||
if val { | ||
*r |= 1 << pos | ||
} else { | ||
*r &= ^(1 << pos) | ||
} | ||
} | ||
|
Oops, something went wrong.